Chameleon

Chameleon Svn Source Tree

Root/branches/rekursor/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 * otherwise 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);
189else // rekursor: if no default pciroot is set in the boot.plist file then go and get this PciRootID:
190 PciRootID =(uint32_t) ascii_hex_to_int(&path[strlen(pciroot_string)]);
191
192if(strncmp(path, pciroot_string, strlen(pciroot_string)))
193{
194printf("ERROR parsing device path\n");
195return NULL;
196}
197
198memset(device, 0, sizeof(struct DevPropDevice));
199
200device->acpi_dev_path._UID = PciRootID;
201
202int numpaths = 0;
203intx, curr = 0;
204charbuff[] = "00";
205
206for(x = 0; x < strlen(path); x++)
207{
208if(!strncmp(&path[x], pci_device_string, strlen(pci_device_string)))
209{
210x+=strlen(pci_device_string);
211curr=x;
212while(path[++x] != ',');
213if(x-curr == 2)
214sprintf(buff, "%c%c", path[curr], path[curr+1]);
215else if(x-curr == 1)
216sprintf(buff, "%c", path[curr]);
217else
218{
219printf("ERROR parsing device path\n");
220numpaths = 0;
221break;
222}
223device->pci_dev_path[numpaths].device =ascii_hex_to_int(buff);
224
225x += 3; // 0x
226curr = x;
227while(path[++x] != ')');
228if(x-curr == 2)
229sprintf(buff, "%c%c", path[curr], path[curr+1]);
230else if(x-curr == 1)
231sprintf(buff, "%c", path[curr]);
232else
233{
234printf("ERROR parsing device path\n");
235numpaths = 0;
236break;
237}
238device->pci_dev_path[numpaths].function = ascii_hex_to_int(buff); // TODO: find dev from char *path
239
240numpaths++;
241}
242}
243
244if(!numpaths)
245return NULL;
246
247device->numentries = 0x00;
248
249device->acpi_dev_path.length = 0x0c;
250device->acpi_dev_path.type = 0x02;
251device->acpi_dev_path.subtype = 0x01;
252device->acpi_dev_path._HID = 0xd041030a;
253
254device->num_pci_devpaths = numpaths;
255device->length = 24 + (6*numpaths);
256
257inti;
258
259for(i = 0; i < numpaths; i++)
260{
261device->pci_dev_path[i].length = 0x06;
262device->pci_dev_path[i].type = 0x01;
263device->pci_dev_path[i].subtype = 0x01;
264}
265
266device->path_end.length = 0x04;
267device->path_end.type = 0x7f;
268device->path_end.subtype = 0xff;
269
270device->string = string;
271device->data = NULL;
272string->length += device->length;
273
274if(!string->entries)
275if((string->entries = (struct DevPropDevice**)MALLOC(sizeof(device)))== NULL)
276return 0;
277
278string->entries[string->numentries++] = (struct DevPropDevice*)MALLOC(sizeof(device));
279string->entries[string->numentries-1] = device;
280
281return device;
282}
283
284int devprop_add_value(struct DevPropDevice *device, char *nm, uint8_t *vl, uint32_t len)
285{
286
287if(!nm || !vl || !len)
288return 0;
289
290uint32_t length = ((strlen(nm) * 2) + len + (2 * sizeof(uint32_t)) + 2);
291uint8_t *data = (uint8_t*)MALLOC(length);
292{
293if(!data)
294return 0;
295
296memset(data, 0, length);
297uint32_t off= 0;
298data[off+1] = ((strlen(nm) * 2) + 6) >> 8;
299data[off] = ((strlen(nm) * 2) + 6) & 0x00FF;
300
301off += 4;
302uint32_t i=0, l = strlen(nm);
303for(i = 0 ; i < l ; i++, off += 2)
304{
305data[off] = *nm++;
306}
307
308off += 2;
309l = len;
310uint32_t *datalength = (uint32_t*)&data[off];
311*datalength = l + 4;
312off += 4;
313for(i = 0 ; i < l ; i++, off++)
314{
315data[off] = *vl++;
316}
317}
318
319uint32_t offset = device->length - (24 + (6 * device->num_pci_devpaths));
320
321uint8_t *newdata = (uint8_t*)MALLOC((length + offset));
322if(!newdata)
323return 0;
324if(device->data)
325if(offset > 1)
326memcpy(newdata, device->data, offset);
327
328memcpy(newdata + offset, data, length);
329
330device->length += length;
331device->string->length += length;
332device->numentries++;
333
334if(!device->data)
335device->data = (uint8_t*)MALLOC(sizeof(uint8_t));
336else
337free(device->data);
338
339free(data);
340device->data = newdata;
341
342return 1;
343}
344
345char *devprop_generate_string(struct DevPropString *string)
346{
347char *buffer = (char*)MALLOC(string->length * 2);
348char *ptr = buffer;
349
350if(!buffer)
351return NULL;
352
353sprintf(buffer, "%08x%08x%04x%04x", dp_swap32(string->length), string->WHAT2,
354dp_swap16(string->numentries), string->WHAT3);
355buffer += 24;
356int i = 0, x = 0;
357
358while(i < string->numentries)
359{
360sprintf(buffer, "%08x%04x%04x", dp_swap32(string->entries[i]->length),
361dp_swap16(string->entries[i]->numentries), string->entries[i]->WHAT2);
362
363buffer += 16;
364sprintf(buffer, "%02x%02x%04x%08x%08x", string->entries[i]->acpi_dev_path.type,
365string->entries[i]->acpi_dev_path.subtype,
366dp_swap16(string->entries[i]->acpi_dev_path.length),
367string->entries[i]->acpi_dev_path._HID,
368dp_swap32(string->entries[i]->acpi_dev_path._UID));
369
370buffer += 24;
371for(x=0;x < string->entries[i]->num_pci_devpaths; x++)
372{
373sprintf(buffer, "%02x%02x%04x%02x%02x", string->entries[i]->pci_dev_path[x].type,
374string->entries[i]->pci_dev_path[x].subtype,
375dp_swap16(string->entries[i]->pci_dev_path[x].length),
376string->entries[i]->pci_dev_path[x].function,
377string->entries[i]->pci_dev_path[x].device);
378buffer += 12;
379}
380
381sprintf(buffer, "%02x%02x%04x", string->entries[i]->path_end.type,
382string->entries[i]->path_end.subtype,
383dp_swap16(string->entries[i]->path_end.length));
384
385buffer += 8;
386uint8_t *dataptr = string->entries[i]->data;
387for(x = 0; x < (string->entries[i]->length) - (24 + (6 * string->entries[i]->num_pci_devpaths)) ; x++)
388{
389sprintf(buffer, "%02x", *dataptr++);
390buffer += 2;
391}
392i++;
393}
394return ptr;
395}
396
397void devprop_free_string(struct DevPropString *string)
398{
399if(!string)
400return;
401
402int i;
403for(i = 0; i < string->numentries; i++)
404{
405if(string->entries[i])
406{
407if(string->entries[i]->data)
408{
409free(string->entries[i]->data);
410string->entries[i]->data = NULL;
411}
412free(string->entries[i]);
413string->entries[i] = NULL;
414}
415}
416
417free(string);
418string = NULL;
419}
420
421/* a fine place for this code */
422
423int devprop_add_network_template(struct DevPropDevice *device, uint16_t vendor_id)
424{
425if(!device)
426return 0;
427uint8_t builtin = 0x0;
428char tmp[10];
429if((vendor_id != 0x168c) && (builtin_set == 0))
430{
431builtin_set = 1;
432builtin = 0x01;
433}
434if(!devprop_add_value(device, "built-in", (uint8_t*)&builtin, 1))
435return 0;
436sprintf(tmp, "Slot-%x",devices_number); // 1 - vga card. FIXME - for 2+ vgas
437if(!devprop_add_value(device, "AAPL,slot-name", tmp, strlen(tmp)))
438return 0;
439devices_number++;
440return 1;
441}
442
443void set_eth_builtin(pci_dt_t *eth_dev)
444{
445char *devicepath = get_pci_dev_path(eth_dev);
446struct DevPropDevice *device = (struct DevPropDevice*)MALLOC(sizeof(struct DevPropDevice));
447
448verbose("LAN Controller [%04x:%04x] :: %s\n", eth_dev->vendor_id, eth_dev->device_id, devicepath);
449
450if (!string)
451string = devprop_create_string();
452
453device = devprop_add_device(string, devicepath);
454if(device)
455{
456verbose("Setting up lan keys\n");
457devprop_add_network_template(device, eth_dev->vendor_id);
458stringdata = (uint8_t*)MALLOC(sizeof(uint8_t) * string->length);
459if(stringdata)
460{
461memcpy(stringdata, (uint8_t*)devprop_generate_string(string), string->length);
462stringlength = string->length;
463}
464}
465}
466

Archive Download this file

Revision: 4