Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 2658