Subversion Repositories Kolibri OS

Rev

Rev 5270 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5096 serge 1
 
2
#include 
3
#include 
4
#include 
5
#include 
6
#include 
7
#include 
8
9
 
10
#define pr_info  printf
11
12
 
13
{
14
    return malloc(len);
15
};
16
17
 
18
 * DMI stands for "Desktop Management Interface".  It is part
19
 * of and an antecedent to, SMBIOS, which stands for System
20
 * Management BIOS.  See further: http://www.dmtf.org/standards
21
 */
22
static const char dmi_empty_string[] = "        ";
23
24
 
25
/*
26
 * Catch too early calls to dmi_check_system():
27
 */
28
static int dmi_initialized;
29
30
 
31
static char dmi_ids_string[128];
32
33
 
34
	const char *device;
35
	const char *bank;
36
	u16 handle;
37
} *dmi_memdev;
38
static int dmi_memdev_nr;
39
40
 
41
{
42
    const u8 *bp = ((u8 *) dm) + dm->length;
43
44
 
45
        s--;
46
        while (s > 0 && *bp) {
47
            bp += strlen(bp) + 1;
48
            s--;
49
        }
50
51
 
52
            size_t len = strlen(bp)+1;
53
            size_t cmp_len = len > 8 ? 8 : len;
54
55
 
56
                return dmi_empty_string;
57
            return bp;
58
        }
59
    }
60
61
 
62
}
63
64
 
65
{
66
    const char *bp = dmi_string_nosave(dm, s);
67
    char *str;
68
    size_t len;
69
70
 
71
        return dmi_empty_string;
72
73
 
74
    str = dmi_alloc(len);
75
    if (str != NULL)
76
        strcpy(str, bp);
77
78
 
79
}
80
81
 
82
 *	We have to be cautious here. We have seen BIOSes with DMI pointers
83
 *	pointing to completely the wrong place for example
84
 */
85
static void dmi_table(u8 *buf, int len, int num,
86
		      void (*decode)(const struct dmi_header *, void *),
87
		      void *private_data)
88
{
89
	u8 *data = buf;
90
	int i = 0;
91
92
 
93
	 *	Stop when we see all the items the table claimed to have
94
	 *	OR we run off the end of the table (also happens)
95
	 */
96
	while ((i < num) && (data - buf + sizeof(struct dmi_header)) <= len) {
97
		const struct dmi_header *dm = (const struct dmi_header *)data;
98
99
 
100
		 *  We want to know the total length (formatted area and
101
		 *  strings) before decoding to make sure we won't run off the
102
		 *  table in dmi_decode or dmi_string
103
		 */
104
		data += dm->length;
105
		while ((data - buf < len - 1) && (data[0] || data[1]))
106
			data++;
107
		if (data - buf < len - 1)
108
			decode(dm, private_data);
109
		data += 2;
110
		i++;
111
	}
112
}
113
114
 
115
static u16 dmi_len;
116
static u16 dmi_num;
117
118
 
119
        void *))
120
{
121
	u8 *buf;
122
123
 
124
	if (buf == NULL)
125
		return -1;
126
127
 
128
129
 
130
131
 
132
}
133
134
 
135
{
136
    u8 sum = 0;
137
    int a;
138
139
 
140
        sum += buf[a];
141
142
 
143
}
144
145
 
146
static LIST_HEAD(dmi_devices);
147
int dmi_available;
148
149
 
150
 *  Save a DMI string
151
 */
152
static void __init dmi_save_ident(const struct dmi_header *dm, int slot,
153
        int string)
154
{
155
    const char *d = (const char *) dm;
156
    const char *p;
157
158
 
159
        return;
160
161
 
162
    if (p == NULL)
163
        return;
164
165
 
166
}
167
168
 
169
        int index)
170
{
171
    const u8 *d = (u8 *) dm + index;
172
    char *s;
173
    int is_ff = 1, is_00 = 1, i;
174
175
 
176
        return;
177
178
 
179
        if (d[i] != 0x00)
180
            is_00 = 0;
181
        if (d[i] != 0xFF)
182
            is_ff = 0;
183
    }
184
185
 
186
        return;
187
188
 
189
    if (!s)
190
        return;
191
192
 
193
     * As of version 2.6 of the SMBIOS specification, the first 3 fields of
194
     * the UUID are supposed to be little-endian encoded.  The specification
195
     * says that this is the defacto standard.
196
     */
197
    if (dmi_ver >= 0x0206)
198
        sprintf(s, "%pUL", d);
199
    else
200
        sprintf(s, "%pUB", d);
201
202
 
203
}
204
205
 
206
        int index)
207
{
208
    const u8 *d = (u8 *) dm + index;
209
    char *s;
210
211
 
212
        return;
213
214
 
215
    if (!s)
216
        return;
217
218
 
219
    dmi_ident[slot] = s;
220
}
221
222
 
223
{
224
    struct dmi_device *dev;
225
226
 
227
    if (dmi_find_device(type, name, NULL))
228
        return;
229
230
 
231
    if (!dev)
232
        return;
233
234
 
235
    strcpy((char *)(dev + 1), name);
236
    dev->name = (char *)(dev + 1);
237
    dev->device_data = NULL;
238
    list_add(&dev->list, &dmi_devices);
239
}
240
241
 
242
{
243
    int i, count = (dm->length - sizeof(struct dmi_header)) / 2;
244
245
 
246
        const char *d = (char *)(dm + 1) + (i * 2);
247
248
 
249
        if ((*d & 0x80) == 0)
250
            continue;
251
252
 
253
    }
254
}
255
256
 
257
{
258
    int i, count = *(u8 *)(dm + 1);
259
    struct dmi_device *dev;
260
261
 
262
        const char *devname = dmi_string(dm, i);
263
264
 
265
            continue;
266
267
 
268
        if (!dev)
269
            break;
270
271
 
272
        dev->name = devname;
273
        dev->device_data = NULL;
274
275
 
276
    }
277
}
278
279
 
280
{
281
	struct dmi_device *dev;
282
	void *data;
283
284
 
285
	if (data == NULL)
286
		return;
287
288
 
289
290
 
291
	if (!dev)
292
		return;
293
294
 
295
	dev->name = "IPMI controller";
296
	dev->device_data = data;
297
298
 
299
}
300
301
 
302
					int devfn, const char *name)
303
{
304
	struct dmi_dev_onboard *onboard_dev;
305
306
 
307
	if (!onboard_dev)
308
		return;
309
310
 
311
	onboard_dev->segment = segment;
312
	onboard_dev->bus = bus;
313
	onboard_dev->devfn = devfn;
314
315
 
316
	onboard_dev->dev.type = DMI_DEV_TYPE_DEV_ONBOARD;
317
	onboard_dev->dev.name = (char *)&onboard_dev[1];
318
	onboard_dev->dev.device_data = onboard_dev;
319
320
 
321
}
322
323
 
324
{
325
	const u8 *d = (u8 *) dm + 5;
326
327
 
328
	if ((*d & 0x80) == 0)
329
		return;
330
331
 
332
			     dmi_string_nosave(dm, *(d-1)));
333
	dmi_save_one_device(*d & 0x7f, dmi_string_nosave(dm, *(d - 1)));
334
335
 
336
337
 
338
 *  Process a DMI table entry. Right now all we care about are the BIOS
339
 *  and machine entries. For 2.5 we should pull the smbus controller info
340
 *  out of here.
341
 */
342
static void __init dmi_decode(const struct dmi_header *dm, void *dummy)
343
{
344
    switch (dm->type) {
345
    case 0:     /* BIOS Information */
346
        dmi_save_ident(dm, DMI_BIOS_VENDOR, 4);
347
        dmi_save_ident(dm, DMI_BIOS_VERSION, 5);
348
        dmi_save_ident(dm, DMI_BIOS_DATE, 8);
349
        break;
350
    case 1:     /* System Information */
351
        dmi_save_ident(dm, DMI_SYS_VENDOR, 4);
352
        dmi_save_ident(dm, DMI_PRODUCT_NAME, 5);
353
        dmi_save_ident(dm, DMI_PRODUCT_VERSION, 6);
354
        dmi_save_ident(dm, DMI_PRODUCT_SERIAL, 7);
355
        dmi_save_uuid(dm, DMI_PRODUCT_UUID, 8);
356
        break;
357
    case 2:     /* Base Board Information */
358
        dmi_save_ident(dm, DMI_BOARD_VENDOR, 4);
359
        dmi_save_ident(dm, DMI_BOARD_NAME, 5);
360
        dmi_save_ident(dm, DMI_BOARD_VERSION, 6);
361
        dmi_save_ident(dm, DMI_BOARD_SERIAL, 7);
362
        dmi_save_ident(dm, DMI_BOARD_ASSET_TAG, 8);
363
        break;
364
    case 3:     /* Chassis Information */
365
        dmi_save_ident(dm, DMI_CHASSIS_VENDOR, 4);
366
        dmi_save_type(dm, DMI_CHASSIS_TYPE, 5);
367
        dmi_save_ident(dm, DMI_CHASSIS_VERSION, 6);
368
        dmi_save_ident(dm, DMI_CHASSIS_SERIAL, 7);
369
        dmi_save_ident(dm, DMI_CHASSIS_ASSET_TAG, 8);
370
        break;
371
    case 10:    /* Onboard Devices Information */
372
        dmi_save_devices(dm);
373
        break;
374
    case 11:    /* OEM Strings */
375
        dmi_save_oem_strings_devices(dm);
376
        break;
377
    case 38:    /* IPMI Device Information */
378
        dmi_save_ipmi_device(dm);
379
        break;
380
    case 41:    /* Onboard Devices Extended Information */
381
        dmi_save_extended_devices(dm);
382
    }
383
}
384
385
 
386
{
387
	int c = 0;
388
	const char *p;
389
390
 
391
		return c;
392
393
 
394
		if (isprint(*p))
395
			c += scnprintf(buf + c, len - c, "%c", *p);
396
		else
397
			c += scnprintf(buf + c, len - c, "\\x%02x", *p & 0xff);
398
	return c;
399
}
400
401
 
402
{
403
    int c = 0;
404
    const char *board;  /* Board Name is optional */
405
406
 
407
                dmi_get_system_info(DMI_SYS_VENDOR));
408
    c += scnprintf(buf + c, len - c, " ");
409
    c += print_filtered(buf + c, len - c,
410
                dmi_get_system_info(DMI_PRODUCT_NAME));
411
412
 
413
    if (board) {
414
        c += scnprintf(buf + c, len - c, "/");
415
        c += print_filtered(buf + c, len - c, board);
416
    }
417
    c += scnprintf(buf + c, len - c, ", BIOS ");
418
    c += print_filtered(buf + c, len - c,
419
                dmi_get_system_info(DMI_BIOS_VERSION));
420
    c += scnprintf(buf + c, len - c, " ");
421
    c += print_filtered(buf + c, len - c,
422
                dmi_get_system_info(DMI_BIOS_DATE));
423
}
424
425
 
426
 * Check for DMI/SMBIOS headers in the system firmware image.  Any
427
 * SMBIOS header must start 16 bytes before the DMI header, so take a
428
 * 32 byte buffer and check for DMI at offset 16 and SMBIOS at offset
429
 * 0.  If the DMI header is present, set dmi_ver accordingly (SMBIOS
430
 * takes precedence) and return 0.  Otherwise return 1.
431
 */
432
static int __init dmi_present(const u8 *buf)
433
{
434
    int smbios_ver;
435
436
 
437
        buf[5] < 32 && dmi_checksum(buf, buf[5])) {
438
        smbios_ver = (buf[6] << 8) + buf[7];
439
440
 
441
        switch (smbios_ver) {
442
        case 0x021F:
443
        case 0x0221:
444
            pr_debug("SMBIOS version fixup(2.%d->2.%d)\n",
445
                 smbios_ver & 0xFF, 3);
446
            smbios_ver = 0x0203;
447
            break;
448
        case 0x0233:
449
            pr_debug("SMBIOS version fixup(2.%d->2.%d)\n", 51, 6);
450
            smbios_ver = 0x0206;
451
            break;
452
        }
453
    } else {
454
        smbios_ver = 0;
455
    }
456
457
 
458
459
 
460
        dmi_num = (buf[13] << 8) | buf[12];
461
        dmi_len = (buf[7] << 8) | buf[6];
462
        dmi_base = (buf[11] << 24) | (buf[10] << 16) |
463
            (buf[9] << 8) | buf[8];
464
465
 
466
            if (smbios_ver) {
467
                dmi_ver = smbios_ver;
468
                pr_info("SMBIOS %d.%d present.\n",
469
                       dmi_ver >> 8, dmi_ver & 0xFF);
470
            } else {
471
                dmi_ver = (buf[14] & 0xF0) << 4 |
472
                       (buf[14] & 0x0F);
473
                pr_info("Legacy DMI %d.%d present.\n",
474
                       dmi_ver >> 8, dmi_ver & 0xFF);
475
            }
476
			dmi_format_ids(dmi_ids_string, sizeof(dmi_ids_string));
477
			printk(KERN_DEBUG "DMI: %s\n", dmi_ids_string);
478
            return 0;
479
        }
480
    }
481
482
 
483
}
484
485
 
486
{
487
    char __iomem *p, *q;
488
	char buf[32];
489
490
 
491
 
492
 
493
494
 
495
     * Iterate over all possible DMI header addresses q.
496
     * Maintain the 32 bytes around q in buf.  On the
497
     * first iteration, substitute zero for the
498
     * out-of-range bytes so there is no chance of falsely
499
     * detecting an SMBIOS header.
500
     */
501
    memset(buf, 0, 16);
502
    for (q = p; q < p + 0x10000; q += 16) {
503
        memcpy(buf + 16, q, 16);
504
        if (!dmi_present(buf)) {
505
            dmi_available = 1;
506
            goto out;
507
        }
508
        memcpy(buf, buf + 16, 16);
509
    }
510
 error:
511
    pr_info("DMI not present or invalid.\n");
512
 out:
513
    dmi_initialized = 1;
514
}
515
516
 
517
/**
518
 *	dmi_matches - check if dmi_system_id structure matches system DMI data
519
 *	@dmi: pointer to the dmi_system_id structure to check
520
 */
521
static bool dmi_matches(const struct dmi_system_id *dmi)
522
{
523
	int i;
524
525
 
526
527
 
528
		int s = dmi->matches[i].slot;
529
		if (s == DMI_NONE)
530
			break;
531
		if (dmi_ident[s]) {
532
			if (!dmi->matches[i].exact_match &&
533
			    strstr(dmi_ident[s], dmi->matches[i].substr))
534
				continue;
535
			else if (dmi->matches[i].exact_match &&
536
				 !strcmp(dmi_ident[s], dmi->matches[i].substr))
537
				continue;
538
		}
539
540
 
541
		return false;
542
	}
543
	return true;
544
}
545
546
 
547
 *	dmi_is_end_of_table - check for end-of-table marker
548
 *	@dmi: pointer to the dmi_system_id structure to check
549
 */
550
static bool dmi_is_end_of_table(const struct dmi_system_id *dmi)
551
{
552
	return dmi->matches[0].slot == DMI_NONE;
553
}
554
555
 
556
 *	dmi_check_system - check system DMI data
557
 *	@list: array of dmi_system_id structures to match against
558
 *		All non-null elements of the list must match
559
 *		their slot's (field index's) data (i.e., each
560
 *		list string must be a substring of the specified
561
 *		DMI slot's string data) to be considered a
562
 *		successful match.
563
 *
564
 *	Walk the blacklist table running matching functions until someone
565
 *	returns non zero or we hit the end. Callback function is called for
566
 *	each successful match. Returns the number of matches.
567
 */
568
int dmi_check_system(const struct dmi_system_id *list)
569
{
570
	int count = 0;
571
	const struct dmi_system_id *d;
572
573
 
574
		if (dmi_matches(d)) {
575
			count++;
576
			if (d->callback && d->callback(d))
577
				break;
578
		}
579
580
 
581
}
582
EXPORT_SYMBOL(dmi_check_system);
583
584
 
585
 *  dmi_get_system_info - return DMI data value
586
 *  @field: data index (see enum dmi_field)
587
 *
588
 *  Returns one DMI data value, can be used to perform
589
 *  complex DMI data checks.
590
 */
591
const char *dmi_get_system_info(int field)
592
{
593
    return dmi_ident[field];
594
}
595
EXPORT_SYMBOL(dmi_get_system_info);
596
/**
597
 *	dmi_find_device - find onboard device by type/name
598
 *	@type: device type or %DMI_DEV_TYPE_ANY to match all device types
599
 *	@name: device name string or %NULL to match all
600
 *	@from: previous device found in search, or %NULL for new search.
601
 *
602
 *	Iterates through the list of known onboard devices. If a device is
603
 *	found with a matching @vendor and @device, a pointer to its device
604
 *	structure is returned.  Otherwise, %NULL is returned.
605
 *	A new search is initiated by passing %NULL as the @from argument.
606
 *	If @from is not %NULL, searches continue from next device.
607
 */
608
const struct dmi_device *dmi_find_device(int type, const char *name,
609
				    const struct dmi_device *from)
610
{
611
	const struct list_head *head = from ? &from->list : &dmi_devices;
612
	struct list_head *d;
613
614
 
615
		const struct dmi_device *dev =
616
			list_entry(d, struct dmi_device, list);
617
618
 
619
		    ((name == NULL) || (strcmp(dev->name, name) == 0)))
620
			return dev;
621
	}
622
623
 
624
}
625
EXPORT_SYMBOL(dmi_find_device);
626