1 | /*␊ |
2 | *␉Copyright 2009 Jasmin Fazlic All rights reserved.␊ |
3 | */␊ |
4 | /*␊ |
5 | *␉Cleaned and merged by iNDi␊ |
6 | */␊ |
7 | ␊ |
8 | #include "libsaio.h"␊ |
9 | #include "bootstruct.h"␊ |
10 | #include "pci.h"␊ |
11 | #include "pci_root.h"␊ |
12 | #include "device_inject.h"␊ |
13 | #include "convert.h"␊ |
14 | #include "platform.h"␊ |
15 | ␊ |
16 | #ifndef DEBUG_INJECT␊ |
17 | #define DEBUG_INJECT 0␊ |
18 | #endif␊ |
19 | ␊ |
20 | #if DEBUG_INJECT␊ |
21 | #define DBG(x...)␉printf(x)␊ |
22 | #else␊ |
23 | #define DBG(x...)␊ |
24 | #endif␊ |
25 | ␊ |
26 | char *efi_inject_get_devprop_string(uint32_t *len)␊ |
27 | {␊ |
28 | struct DevPropString *string = (struct DevPropString *)(uint32_t)get_env(envEFIString);␊ |
29 | ␊ |
30 | ␉if(string)␊ |
31 | ␉{␊ |
32 | ␉␉*len = string->length;␊ |
33 | ␉␉return devprop_generate_string(string);␊ |
34 | ␉}␊ |
35 | ␉verbose("efi_inject_get_devprop_string NULL trying stringdata\n");␊ |
36 | ␉return NULL;␊ |
37 | }␊ |
38 | ␊ |
39 | void setupDeviceProperties(Node *node)␊ |
40 | {␊ |
41 | ␉const char *val;␊ |
42 | ␉uint8_t *binStr;␊ |
43 | uint8_t *kbinStr;␊ |
44 | ␊ |
45 | ␉int cnt, cnt2;␊ |
46 | ␉␊ |
47 | ␉static char DEVICE_PROPERTIES_PROP[] = "device-properties";␊ |
48 | ␉␊ |
49 | ␉/* Generate devprop string.␊ |
50 | ␉ */␊ |
51 | ␉uint32_t strlength;␊ |
52 | ␉char *string = efi_inject_get_devprop_string(&strlength);␊ |
53 | ␉␊ |
54 | ␉/* Use the static "device-properties" boot config key contents if available,␊ |
55 | ␉ * otheriwse use the generated one.␊ |
56 | ␉ */ ␊ |
57 | ␉if (!getValueForKey(kDeviceProperties, &val, &cnt, DEFAULT_BOOT_CONFIG) && string)␊ |
58 | ␉{␊ |
59 | ␉␉val = (const char*)string;␊ |
60 | ␉␉cnt = strlength * 2;␊ |
61 | ␉} ␊ |
62 | ␊ |
63 | ␉if (cnt > 1)␊ |
64 | ␉{␊ |
65 | ␉␉binStr = convertHexStr2Binary(val, &cnt2); ␊ |
66 | ␊ |
67 | if (cnt2 > 0)␊ |
68 | {␊ |
69 | kbinStr = (uint8_t*)AllocateKernelMemory(cnt2); ␊ |
70 | bcopy(binStr,kbinStr,cnt2); ␊ |
71 | DT__AddProperty(node, DEVICE_PROPERTIES_PROP, cnt2, kbinStr);␊ |
72 | }␊ |
73 | ␉}␊ |
74 | }␊ |
75 | ␊ |
76 | struct DevPropString *devprop_create_string(void)␊ |
77 | {␊ |
78 | ␉struct DevPropString *string = (struct DevPropString*)malloc(sizeof(struct DevPropString));␊ |
79 | ␉␊ |
80 | ␉if(string == NULL)␊ |
81 | ␉{␊ |
82 | ␉␉return NULL;␊ |
83 | ␉}␊ |
84 | ␉␊ |
85 | ␉memset(string, 0, sizeof(struct DevPropString));␊ |
86 | ␉string->length = 12;␊ |
87 | ␉string->WHAT2 = 0x01000000;␊ |
88 | ␉return string;␊ |
89 | }␊ |
90 | ␊ |
91 | struct DevPropDevice *devprop_make_device(pci_dt_t *pci_dt)␊ |
92 | {␊ |
93 | ␉struct DevPropDevice␉*device;␊ |
94 | int numpaths = 0;␊ |
95 | ␊ |
96 | ␉pci_dt_t␉*current;␊ |
97 | ␉pci_dt_t␉*end;␊ |
98 | ␉␊ |
99 | ␉end = root_pci_dev;␊ |
100 | ␊ |
101 | ␉device = malloc(sizeof(struct DevPropDevice));␊ |
102 | ␉if (!device) {␊ |
103 | return NULL;␊ |
104 | }␊ |
105 | memset(device, 0, sizeof(struct DevPropDevice));␊ |
106 | ␊ |
107 | ␉device->acpi_dev_path._UID = getPciRootUID();␊ |
108 | ␉while (end != pci_dt)␊ |
109 | ␉{␊ |
110 | ␉␉current = pci_dt;␊ |
111 | ␉␉while (current->parent != end)␊ |
112 | ␉␉␉current = current->parent;␉␉␉␊ |
113 | ␉␉end = current;␊ |
114 | ␊ |
115 | ␉␉{␊ |
116 | device->pci_dev_path[numpaths].device =␉(uint8_t)current->dev.bits.dev;␊ |
117 | ␉␉␉device->pci_dev_path[numpaths].function = (uint8_t)current->dev.bits.func;␊ |
118 | numpaths++;␊ |
119 | ␉␉} ␊ |
120 | ␉␉␊ |
121 | ␉}␊ |
122 | ␉␉␉␊ |
123 | ␉if(!numpaths)␊ |
124 | ␉{␊ |
125 | printf("ERROR parsing device path\n");␊ |
126 | free(device);␊ |
127 | ␉␉return NULL;␊ |
128 | ␉}␊ |
129 | ␉␊ |
130 | ␉device->numentries = 0x00;␊ |
131 | ␉␊ |
132 | ␉device->acpi_dev_path.length = 0x0c;␊ |
133 | ␉device->acpi_dev_path.type = 0x02;␊ |
134 | ␉device->acpi_dev_path.subtype = 0x01;␊ |
135 | ␉device->acpi_dev_path._HID = 0xd041030a;␊ |
136 | ␉␊ |
137 | ␉device->num_pci_devpaths = numpaths;␊ |
138 | ␉device->length = 24 + (6*numpaths);␊ |
139 | ␉␊ |
140 | ␉int␉␉i; ␊ |
141 | ␉␊ |
142 | ␉for(i = 0; i < numpaths; i++)␊ |
143 | ␉{␊ |
144 | ␉␉device->pci_dev_path[i].length = 0x06;␊ |
145 | ␉␉device->pci_dev_path[i].type = 0x01;␊ |
146 | ␉␉device->pci_dev_path[i].subtype = 0x01;␊ |
147 | ␉}␊ |
148 | ␉␊ |
149 | ␉device->path_end.length = 0x04;␊ |
150 | ␉device->path_end.type = 0x7f;␊ |
151 | ␉device->path_end.subtype = 0xff;␊ |
152 | ␉␊ |
153 | ␉device->data = NULL;␊ |
154 | ␉␉␉␊ |
155 | ␉return device;␊ |
156 | }␊ |
157 | ␊ |
158 | struct DevPropDevice *devprop_add_device(struct DevPropString *string, pci_dt_t * pci_dt)␊ |
159 | {␊ |
160 | ␉struct DevPropDevice␉*device;␊ |
161 | ␉␉␊ |
162 | ␉if (string == NULL || pci_dt == NULL) {␊ |
163 | ␉␉return NULL;␊ |
164 | ␉}␊ |
165 | ␉device = devprop_make_device(pci_dt);␊ |
166 | ␉if (!device) {␊ |
167 | return NULL;␊ |
168 | }␊ |
169 | ␉␉␊ |
170 | ␉device->string = string;␊ |
171 | ␉string->length += device->length;␊ |
172 | ␉␊ |
173 | ␉if(!string->entries)␊ |
174 | ␉{␊ |
175 | ␉␉if((string->entries = (struct DevPropDevice*)malloc(sizeof(struct DevPropDevice) * MAX_STRING_NUM_ENTRIES))== NULL)␊ |
176 | ␉␉{␊ |
177 | printf("ERROR parsing device path 2\n");␊ |
178 | ␊ |
179 | free(device);␊ |
180 | ␉␉␉return NULL;␊ |
181 | ␉␉}␊ |
182 | ␉}␊ |
183 | ␉struct DevPropDevice **string_entries_arrey = (struct DevPropDevice **) string->entries;␊ |
184 | ␉␊ |
185 | ␉string->numentries++;␊ |
186 | ␊ |
187 | ␉string_entries_arrey[string->numentries-1] = device;␊ |
188 | ␉␊ |
189 | ␉return device;␊ |
190 | }␊ |
191 | ␊ |
192 | #if 0␊ |
193 | struct DevPropDevice *devprop_add_device(struct DevPropString *string, char *path)␊ |
194 | {␊ |
195 | ␉struct DevPropDevice␉*device;␊ |
196 | ␉const char␉␉pciroot_string[] = "PciRoot(0x";␊ |
197 | ␉const char␉␉pci_device_string[] = "Pci(0x";␊ |
198 | ␉␊ |
199 | ␉if (string == NULL || path == NULL) {␊ |
200 | ␉␉return NULL;␊ |
201 | ␉}␊ |
202 | ␉device = malloc(sizeof(struct DevPropDevice));␊ |
203 | ␉if (!device) {␊ |
204 | return NULL;␊ |
205 | }␊ |
206 | ␉if (strncmp(path, pciroot_string, strlen(pciroot_string))) {␊ |
207 | free(device);␊ |
208 | ␉␉printf("ERROR parsing device path 1\n");␊ |
209 | ␉␉return NULL;␊ |
210 | ␉}␊ |
211 | ␉␊ |
212 | ␉memset(device, 0, sizeof(struct DevPropDevice));␊ |
213 | ␉device->acpi_dev_path._UID = getPciRootUID();␊ |
214 | ␉␊ |
215 | ␉int numpaths = 0;␊ |
216 | ␉int␉␉x, curr = 0, w = 0;␊ |
217 | ␊ |
218 | ␉char␉buff[16];␊ |
219 | ␉␊ |
220 | ␊ |
221 | ␉for (x = 0; x < strlen(path); x++) ␊ |
222 | ␉{␊ |
223 | ␊ |
224 | ␉␉if (!strncmp(&path[x], pci_device_string, strlen(pci_device_string)))␊ |
225 | ␉␉{␊ |
226 | ␉␉␉x+=strlen(pci_device_string);␊ |
227 | ␉␉␉curr=x;␊ |
228 | ␉␉␉while(path[++x] != ',');␊ |
229 | ␊ |
230 | w = x-curr;␊ |
231 | ␊ |
232 | if ((w > 4) || /*(w > sizeof(buff)) ||*/ (w == 0)) {␊ |
233 | printf("ERROR parsing device path 2\n");␊ |
234 | break;␊ |
235 | }␊ |
236 | ␊ |
237 | snprintf(buff, x-curr, "%s",&path[curr]);␊ |
238 | ␉␉␉␊ |
239 | ␉␉␉device->pci_dev_path[numpaths].device =␉(uint8_t)strtoul(buff, NULL, 16);␊ |
240 | ␉␉␉␊ |
241 | bzero(buff, sizeof(buff));␊ |
242 | ␊ |
243 | ␉␉␉x += 3; // 0x␊ |
244 | ␉␉␉curr = x;␊ |
245 | ␉␉␉while(path[++x] != ')');␊ |
246 | ␊ |
247 | w = x-curr;␊ |
248 | ␊ |
249 | if ((w > 4) || /*(w > sizeof(buff)) ||*/ (w == 0)) {␊ |
250 | printf("ERROR parsing device path 3\n");␊ |
251 | break;␊ |
252 | }␊ |
253 | ␊ |
254 | snprintf(buff, x-curr, "%s",&path[curr]);␊ |
255 | ␊ |
256 | ␉␉␉device->pci_dev_path[numpaths].function = (uint8_t)strtoul(buff, NULL, 16); // TODO: find dev from char *path␊ |
257 | ␉␉␉␊ |
258 | ␉␉␉numpaths++;␊ |
259 | ␉␉}␊ |
260 | ␉}␊ |
261 | ␉␊ |
262 | ␉if(!numpaths)␊ |
263 | ␉{␊ |
264 | printf("ERROR parsing device path 4\n");␊ |
265 | free(device);␊ |
266 | ␉␉return NULL;␊ |
267 | ␉}␊ |
268 | ␉␊ |
269 | ␉device->numentries = 0x00;␊ |
270 | ␉␊ |
271 | ␉device->acpi_dev_path.length = 0x0c;␊ |
272 | ␉device->acpi_dev_path.type = 0x02;␊ |
273 | ␉device->acpi_dev_path.subtype = 0x01;␊ |
274 | ␉device->acpi_dev_path._HID = 0xd041030a;␊ |
275 | ␉␊ |
276 | ␉device->num_pci_devpaths = numpaths;␊ |
277 | ␉device->length = 24 + (6*numpaths);␊ |
278 | ␉␊ |
279 | ␉int␉␉i; ␊ |
280 | ␉␊ |
281 | ␉for(i = 0; i < numpaths; i++)␊ |
282 | ␉{␊ |
283 | ␉␉device->pci_dev_path[i].length = 0x06;␊ |
284 | ␉␉device->pci_dev_path[i].type = 0x01;␊ |
285 | ␉␉device->pci_dev_path[i].subtype = 0x01;␊ |
286 | ␉}␊ |
287 | ␉␊ |
288 | ␉device->path_end.length = 0x04;␊ |
289 | ␉device->path_end.type = 0x7f;␊ |
290 | ␉device->path_end.subtype = 0xff;␊ |
291 | ␉␊ |
292 | ␉device->string = string;␊ |
293 | ␉device->data = NULL;␊ |
294 | ␉string->length += device->length;␊ |
295 | ␉␊ |
296 | ␉if(!string->entries)␊ |
297 | ␉{␊ |
298 | ␉␉if((string->entries = (struct DevPropDevice*)malloc(sizeof(struct DevPropDevice) * MAX_STRING_NUM_ENTRIES))== NULL)␊ |
299 | ␉␉{␊ |
300 | printf("ERROR parsing device path 6\n");␊ |
301 | ␊ |
302 | free(device);␊ |
303 | ␉␉␉return NULL;␊ |
304 | ␉␉}␊ |
305 | ␉}␊ |
306 | ␉struct DevPropDevice **string_entries_arrey = (struct DevPropDevice **) string->entries;␊ |
307 | ␉␊ |
308 | ␉string->numentries++;␊ |
309 | ␊ |
310 | ␉string_entries_arrey[string->numentries-1] = device;␊ |
311 | ␉␊ |
312 | ␉return device;␊ |
313 | }␊ |
314 | #endif␊ |
315 | ␊ |
316 | int devprop_add_value(struct DevPropDevice *device, char *nm, uint8_t *vl, uint32_t len)␊ |
317 | {␊ |
318 | ␉␊ |
319 | ␉if(!nm || !vl || !len)␊ |
320 | ␉{␊ |
321 | ␉␉return 0;␊ |
322 | ␉}␊ |
323 | ␉␊ |
324 | ␉uint32_t length = ((strlen(nm) * 2) + len + (2 * sizeof(uint32_t)) + 2);␊ |
325 | ␉uint8_t *data = (uint8_t*)malloc(length);␊ |
326 | ␉{␊ |
327 | ␉␉if(!data)␊ |
328 | ␉␉{␊ |
329 | ␉␉␉return 0;␊ |
330 | ␉␉}␊ |
331 | ␉␉␊ |
332 | ␉␉memset(data, 0, length);␊ |
333 | ␉␉uint32_t off= 0;␊ |
334 | ␉␉data[off+1] = ((strlen(nm) * 2) + 6) >> 8;␊ |
335 | ␉␉data[off] = ((strlen(nm) * 2) + 6) & 0x00FF;␊ |
336 | ␉␉␊ |
337 | ␉␉off += 4;␊ |
338 | ␉␉uint32_t i=0, l = strlen(nm);␊ |
339 | ␉␉for(i = 0 ; i < l ; i++, off += 2)␊ |
340 | ␉␉{␊ |
341 | ␉␉␉data[off] = *nm++;␊ |
342 | ␉␉}␊ |
343 | ␉␉␊ |
344 | ␉␉off += 2;␊ |
345 | ␉␉l = len;␊ |
346 | ␉␉uint32_t *datalength = (uint32_t*)&data[off];␊ |
347 | ␉␉*datalength = l + 4;␊ |
348 | ␉␉off += 4;␊ |
349 | ␉␉for(i = 0 ; i < l ; i++, off++)␊ |
350 | ␉␉{␊ |
351 | ␉␉␉data[off] = *vl++;␊ |
352 | ␉␉}␊ |
353 | ␉}␉␊ |
354 | ␉␊ |
355 | ␉uint32_t offset = device->length - (24 + (6 * device->num_pci_devpaths));␊ |
356 | ␉␊ |
357 | ␉uint8_t *newdata = (uint8_t*)malloc((length + offset));␊ |
358 | ␉if(!newdata)␊ |
359 | ␉{␊ |
360 | ␉␉return 0;␊ |
361 | ␉}␊ |
362 | ␉if(device->data)␊ |
363 | ␉{␊ |
364 | ␉␉if(offset > 1)␊ |
365 | ␉␉{␊ |
366 | ␉␉␉memcpy(newdata, device->data, offset);␊ |
367 | ␉␉}␊ |
368 | ␉}␊ |
369 | ␉␊ |
370 | ␉memcpy(newdata + offset, data, length);␊ |
371 | ␉␊ |
372 | ␉device->length += length;␊ |
373 | ␉device->string->length += length;␊ |
374 | ␉device->numentries++;␊ |
375 | ␉␊ |
376 | ␉if(!device->data)␊ |
377 | ␉{␊ |
378 | ␉␉//device->data = (uint8_t*)malloc(sizeof(uint8_t)); //IMHO this is useless␊ |
379 | ␉}␊ |
380 | ␉else␊ |
381 | ␉{␊ |
382 | ␉␉free(device->data);␊ |
383 | ␉}␊ |
384 | ␉␊ |
385 | ␉free(data);␊ |
386 | ␉device->data = newdata;␊ |
387 | ␉␊ |
388 | ␉return 1;␊ |
389 | }␊ |
390 | ␊ |
391 | char *devprop_generate_string(struct DevPropString *string)␊ |
392 | {␊ |
393 | ␉char *buffer = (char*)malloc(string->length * 2);␊ |
394 | ␉char *ptr = buffer;␊ |
395 | ␉␊ |
396 | ␉if(!buffer)␊ |
397 | ␉{␊ |
398 | ␉␉return NULL;␊ |
399 | ␉}␊ |
400 | ␉␊ |
401 | ␉sprintf(buffer, "%08x%08x%04x%04x", dp_swap32(string->length), string->WHAT2,␊ |
402 | ␉␉␉dp_swap16(string->numentries), string->WHAT3);␊ |
403 | ␉buffer += 24;␊ |
404 | ␉int i = 0, x = 0;␊ |
405 | ␉␊ |
406 | ␉struct DevPropDevice **string_entries_arrey = (struct DevPropDevice **) string->entries;␊ |
407 | ␊ |
408 | ␉while(i < string->numentries)␊ |
409 | ␉{␊ |
410 | ␉␉sprintf(buffer, "%08x%04x%04x", dp_swap32(string_entries_arrey[i]->length),␊ |
411 | ␉␉␉␉dp_swap16(string_entries_arrey[i]->numentries), string_entries_arrey[i]->WHAT2);␊ |
412 | ␉␉␊ |
413 | ␉␉buffer += 16;␊ |
414 | ␉␉sprintf(buffer, "%02x%02x%04x%08x%08x", string_entries_arrey[i]->acpi_dev_path.type,␊ |
415 | ␉␉␉␉string_entries_arrey[i]->acpi_dev_path.subtype,␊ |
416 | ␉␉␉␉dp_swap16(string_entries_arrey[i]->acpi_dev_path.length),␊ |
417 | ␉␉␉␉string_entries_arrey[i]->acpi_dev_path._HID,␊ |
418 | ␉␉␉␉dp_swap32(string_entries_arrey[i]->acpi_dev_path._UID));␊ |
419 | ␉␉␊ |
420 | ␉␉buffer += 24;␊ |
421 | ␉␉for(x=0;x < string_entries_arrey[i]->num_pci_devpaths; x++)␊ |
422 | ␉␉{␊ |
423 | ␉␉␉sprintf(buffer, "%02x%02x%04x%02x%02x", string_entries_arrey[i]->pci_dev_path[x].type,␊ |
424 | ␉␉␉␉␉string_entries_arrey[i]->pci_dev_path[x].subtype,␊ |
425 | ␉␉␉␉␉dp_swap16(string_entries_arrey[i]->pci_dev_path[x].length),␊ |
426 | ␉␉␉␉␉string_entries_arrey[i]->pci_dev_path[x].function,␊ |
427 | ␉␉␉␉␉string_entries_arrey[i]->pci_dev_path[x].device);␊ |
428 | ␉␉␉buffer += 12;␊ |
429 | ␉␉}␊ |
430 | ␉␉␊ |
431 | ␉␉sprintf(buffer, "%02x%02x%04x", string_entries_arrey[i]->path_end.type,␊ |
432 | ␉␉␉␉string_entries_arrey[i]->path_end.subtype,␊ |
433 | ␉␉␉␉dp_swap16(string_entries_arrey[i]->path_end.length));␊ |
434 | ␉␉␊ |
435 | ␉␉buffer += 8;␊ |
436 | ␉␉uint8_t *dataptr = string_entries_arrey[i]->data;␊ |
437 | ␉␉for(x = 0; (uint32_t)x < (string_entries_arrey[i]->length) - (24 + (6 * string_entries_arrey[i]->num_pci_devpaths)) ; x++)␊ |
438 | ␉␉{␊ |
439 | ␉␉␉sprintf(buffer, "%02x", *dataptr++);␊ |
440 | ␉␉␉buffer += 2;␊ |
441 | ␉␉}␊ |
442 | ␉␉i++;␊ |
443 | ␉}␊ |
444 | ␉return ptr;␊ |
445 | }␊ |
446 | ␊ |
447 | void devprop_free_string(struct DevPropString *string)␊ |
448 | {␊ |
449 | ␉if(!string)␊ |
450 | ␉{␊ |
451 | ␉␉return;␊ |
452 | ␉}␊ |
453 | ␉␊ |
454 | ␉int i;␊ |
455 | ␉␊ |
456 | ␉struct DevPropDevice **string_entries_arrey = (struct DevPropDevice **) string->entries;␊ |
457 | ␊ |
458 | ␉for(i = 0; i < string->numentries; i++)␊ |
459 | ␉{␊ |
460 | ␉␉if(string_entries_arrey[i])␊ |
461 | ␉␉{␊ |
462 | ␉␉␉if(string_entries_arrey[i]->data)␊ |
463 | ␉␉␉{␊ |
464 | ␉␉␉␉free(string_entries_arrey[i]->data);␊ |
465 | ␉␉␉␉string_entries_arrey[i]->data = NULL;␊ |
466 | ␉␉␉}␊ |
467 | ␉␉␉free(string_entries_arrey[i]);␊ |
468 | ␉␉␉string_entries_arrey[i] = NULL;␊ |
469 | ␉␉}␊ |
470 | ␉}␊ |
471 | ␉␊ |
472 | ␉free(string);␊ |
473 | ␉string = NULL;␊ |
474 | } |