Chameleon

Chameleon Svn Source Tree

Root/trunk/i386/libsaio/device_inject.c

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

Archive Download this file

Revision: 1