OSDN Git Service

linux-pci-root: remove an unused assignment
[android-x86/external-efivar.git] / src / linux-acpi-root.c
1 /*
2  * libefiboot - library for the manipulation of EFI boot variables
3  * Copyright 2012-2018 Red Hat, Inc.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public License as
7  * published by the Free Software Foundation; either version 2.1 of the
8  * License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, see
17  * <http://www.gnu.org/licenses/>.
18  *
19  */
20
21 #include "fix_coverity.h"
22
23 #include <errno.h>
24 #include <fcntl.h>
25 #include <inttypes.h>
26 #include <stdint.h>
27 #include <unistd.h>
28
29 #include "efiboot.h"
30
31 /*
32  * support for ACPI-like platform root hub and devices
33  *
34  * various devices /sys/dev/block/$major:$minor start with:
35  * maj:min -> ../../devices/ACPI0000:00/$PCI_DEVICES/$BLOCKDEV_STUFF/block/$DISK/$PART
36  * i.e.:                    APMC0D0D:00/ata1/host0/target0:0:0/0:0:0:0/block/sda
37  *                          ^ root hub ^blockdev stuff
38  * or:
39  * maj:min -> ../../devices/ACPI0000:00/$PCI_DEVICES/$BLOCKDEV_STUFF/block/$DISK/$PART
40  * i.e.:                    APMC0D0D:00/0000:00:1d.0/0000:05:00.0/ata1/host0/target0:0:0/0:0:0:0/block/sda
41  *                          ^ root hub ^pci dev      ^pci dev     ^ blockdev stuff
42  */
43 static ssize_t
44 parse_acpi_root(struct device *dev, const char *current, const char *root UNUSED)
45 {
46         int rc;
47         int pos;
48         uint16_t pad0;
49         uint8_t pad1;
50         char *acpi_header = NULL;
51         char *colon;
52
53         const char *devpart = current;
54         char *spaces;
55
56         pos = strlen(current);
57         spaces = alloca(pos+1);
58         memset(spaces, ' ', pos+1);
59         spaces[pos] = '\0';
60         pos = 0;
61
62         debug("entry");
63
64         /*
65          * find the ACPI root dunno0 and dunno1; they basically look like:
66          * ABCD0000:00/
67          *     ^d0  ^d1
68          * This is annoying because "/%04ms%h:%hhx/" won't bind from the right
69          * side in sscanf.
70          */
71         rc = sscanf(devpart, "../../devices/platform/%n", &pos);
72         debug("devpart:\"%s\" rc:%d pos:%d", devpart, rc, pos);
73         if (rc != 0 || pos < 1)
74                 return 0;
75         devpart += pos;
76
77         /*
78          * If it's too short to be A0000:00, it's not an ACPI string
79          */
80         if (strlen(devpart) < 8)
81                 return 0;
82
83         colon = strchr(devpart, ':');
84         if (!colon)
85                 return 0;
86         pos = colon - devpart;
87
88         /*
89          * If colon doesn't point at something between one of these:
90          * A0000:00 ACPI0000:00
91          *      ^ 5         ^ 8
92          * Then it's not an ACPI string.
93          */
94         if (pos < 5 || pos > 8)
95                 return 0;
96
97         dev->acpi_root.acpi_hid_str = strndup(devpart, pos + 1);
98         if (!dev->acpi_root.acpi_hid_str) {
99                 efi_error("Could not allocate memory");
100                 return -1;
101         }
102         dev->acpi_root.acpi_hid_str[pos] = 0;
103         debug("acpi_hid_str:\"%s\"", dev->acpi_root.acpi_hid_str);
104
105         pos -= 4;
106         debug("devpart:\"%s\" rc:%d pos:%d", devpart, rc, pos);
107         acpi_header = strndupa(devpart, pos);
108         if (!acpi_header)
109                 return 0;
110         acpi_header[pos] = 0;
111         debug("devpart:\"%s\" acpi_header:\"%s\"", devpart, acpi_header);
112         devpart += pos;
113
114         /*
115          * If we can't find these numbers, it's not an ACPI string
116          */
117         rc = sscanf(devpart, "%hx:%hhx/%n", &pad0, &pad1, &pos);
118         if (rc != 2) {
119                 efi_error("Could not parse ACPI path \"%s\"", devpart);
120                 return 0;
121         }
122         debug("devpart:\"%s\" parsed:%04hx:%02hhx pos:%d rc:%d",
123               devpart, pad0, pad1, pos, rc);
124
125         devpart += pos;
126
127         rc = parse_acpi_hid_uid(dev, "devices/platform/%s%04hX:%02hhX",
128                                 acpi_header, pad0, pad1);
129         debug("rc:%d acpi_header:%s pad0:%04hX pad1:%02hhX",
130               rc, acpi_header, pad0, pad1);
131         if (rc < 0 && errno == ENOENT) {
132                 rc = parse_acpi_hid_uid(dev, "devices/platform/%s%04hx:%02hhx",
133                                 acpi_header, pad0, pad1);
134                 debug("rc:%d acpi_header:%s pad0:%04hx pad1:%02hhx",
135                       rc, acpi_header, pad0, pad1);
136         }
137         if (rc < 0) {
138                 efi_error("Could not parse hid/uid");
139                 return rc;
140         }
141         debug("Parsed HID:0x%08x UID:0x%"PRIx64" uidstr:\"%s\" path:\"%s\"",
142               dev->acpi_root.acpi_hid, dev->acpi_root.acpi_uid,
143               dev->acpi_root.acpi_uid_str,
144               dev->acpi_root.acpi_cid_str);
145
146         return devpart - current;
147 }
148
149 static ssize_t
150 dp_create_acpi_root(struct device *dev,
151                     uint8_t *buf, ssize_t size, ssize_t off)
152 {
153         ssize_t sz = 0, new = 0;
154
155         debug("entry buf:%p size:%zd off:%zd", buf, size, off);
156
157         if (dev->acpi_root.acpi_uid_str || dev->acpi_root.acpi_cid_str) {
158                 debug("creating acpi_hid_ex dp hid:0x%08x uid:0x%"PRIx64" uidstr:\"%s\" cidstr:\"%s\"",
159                       dev->acpi_root.acpi_hid, dev->acpi_root.acpi_uid,
160                       dev->acpi_root.acpi_uid_str, dev->acpi_root.acpi_cid_str);
161                 new = efidp_make_acpi_hid_ex(buf + off, size ? size - off : 0,
162                                             dev->acpi_root.acpi_hid,
163                                             dev->acpi_root.acpi_uid,
164                                             dev->acpi_root.acpi_cid,
165                                             dev->acpi_root.acpi_hid_str,
166                                             dev->acpi_root.acpi_uid_str,
167                                             dev->acpi_root.acpi_cid_str);
168                 if (new < 0) {
169                         efi_error("efidp_make_acpi_hid_ex() failed");
170                         return new;
171                 }
172         } else {
173                 debug("creating acpi_hid dp hid:0x%08x uid:0x%0"PRIx64,
174                       dev->acpi_root.acpi_hid,
175                       dev->acpi_root.acpi_uid);
176                 new = efidp_make_acpi_hid(buf + off, size ? size - off : 0,
177                                          dev->acpi_root.acpi_hid,
178                                          dev->acpi_root.acpi_uid);
179                 if (new < 0) {
180                         efi_error("efidp_make_acpi_hid() failed");
181                         return new;
182                 }
183         }
184         sz += new;
185
186         debug("returning %zd", sz);
187         return sz;
188 }
189
190 enum interface_type acpi_root_iftypes[] = { acpi_root, unknown };
191
192 struct dev_probe HIDDEN acpi_root_parser = {
193         .name = "acpi_root",
194         .iftypes = acpi_root_iftypes,
195         .flags = DEV_PROVIDES_ROOT,
196         .parse = parse_acpi_root,
197         .create = dp_create_acpi_root,
198 };