Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 2469