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

Archive Download this file

Revision: 11