Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/firmware/edd.c
26378 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
/*
3
* linux/drivers/firmware/edd.c
4
* Copyright (C) 2002, 2003, 2004 Dell Inc.
5
* by Matt Domsch <[email protected]>
6
* disk signature by Matt Domsch, Andrew Wilks, and Sandeep K. Shandilya
7
* legacy CHS by Patrick J. LoPresti <[email protected]>
8
*
9
* BIOS Enhanced Disk Drive Services (EDD)
10
* conformant to T13 Committee www.t13.org
11
* projects 1572D, 1484D, 1386D, 1226DT
12
*
13
* This code takes information provided by BIOS EDD calls
14
* fn41 - Check Extensions Present and
15
* fn48 - Get Device Parameters with EDD extensions
16
* made in setup.S, copied to safe structures in setup.c,
17
* and presents it in sysfs.
18
*
19
* Please see http://linux.dell.com/edd/results.html for
20
* the list of BIOSs which have been reported to implement EDD.
21
*/
22
23
#include <linux/module.h>
24
#include <linux/string.h>
25
#include <linux/types.h>
26
#include <linux/init.h>
27
#include <linux/stat.h>
28
#include <linux/err.h>
29
#include <linux/ctype.h>
30
#include <linux/slab.h>
31
#include <linux/limits.h>
32
#include <linux/device.h>
33
#include <linux/pci.h>
34
#include <linux/blkdev.h>
35
#include <linux/edd.h>
36
37
#define EDD_VERSION "0.16"
38
#define EDD_DATE "2004-Jun-25"
39
40
MODULE_AUTHOR("Matt Domsch <[email protected]>");
41
MODULE_DESCRIPTION("sysfs interface to BIOS EDD information");
42
MODULE_LICENSE("GPL");
43
MODULE_VERSION(EDD_VERSION);
44
45
#define left (PAGE_SIZE - (p - buf) - 1)
46
47
struct edd_device {
48
unsigned int index;
49
unsigned int mbr_signature;
50
struct edd_info *info;
51
struct kobject kobj;
52
};
53
54
struct edd_attribute {
55
struct attribute attr;
56
ssize_t(*show) (struct edd_device * edev, char *buf);
57
int (*test) (struct edd_device * edev);
58
};
59
60
/* forward declarations */
61
static int edd_dev_is_type(struct edd_device *edev, const char *type);
62
static struct pci_dev *edd_get_pci_dev(struct edd_device *edev);
63
64
static struct edd_device *edd_devices[EDD_MBR_SIG_MAX];
65
66
#define EDD_DEVICE_ATTR(_name,_mode,_show,_test) \
67
struct edd_attribute edd_attr_##_name = { \
68
.attr = {.name = __stringify(_name), .mode = _mode }, \
69
.show = _show, \
70
.test = _test, \
71
};
72
73
static int
74
edd_has_mbr_signature(struct edd_device *edev)
75
{
76
return edev->index < min_t(unsigned char, edd.mbr_signature_nr, EDD_MBR_SIG_MAX);
77
}
78
79
static int
80
edd_has_edd_info(struct edd_device *edev)
81
{
82
return edev->index < min_t(unsigned char, edd.edd_info_nr, EDDMAXNR);
83
}
84
85
static inline struct edd_info *
86
edd_dev_get_info(struct edd_device *edev)
87
{
88
return edev->info;
89
}
90
91
static inline void
92
edd_dev_set_info(struct edd_device *edev, int i)
93
{
94
edev->index = i;
95
if (edd_has_mbr_signature(edev))
96
edev->mbr_signature = edd.mbr_signature[i];
97
if (edd_has_edd_info(edev))
98
edev->info = &edd.edd_info[i];
99
}
100
101
#define to_edd_attr(_attr) container_of(_attr,struct edd_attribute,attr)
102
#define to_edd_device(obj) container_of(obj,struct edd_device,kobj)
103
104
static ssize_t
105
edd_attr_show(struct kobject * kobj, struct attribute *attr, char *buf)
106
{
107
struct edd_device *dev = to_edd_device(kobj);
108
struct edd_attribute *edd_attr = to_edd_attr(attr);
109
ssize_t ret = -EIO;
110
111
if (edd_attr->show)
112
ret = edd_attr->show(dev, buf);
113
return ret;
114
}
115
116
static const struct sysfs_ops edd_attr_ops = {
117
.show = edd_attr_show,
118
};
119
120
static ssize_t
121
edd_show_host_bus(struct edd_device *edev, char *buf)
122
{
123
struct edd_info *info;
124
char *p = buf;
125
int i;
126
127
if (!edev)
128
return -EINVAL;
129
info = edd_dev_get_info(edev);
130
if (!info || !buf)
131
return -EINVAL;
132
133
for (i = 0; i < 4; i++) {
134
if (isprint(info->params.host_bus_type[i])) {
135
p += scnprintf(p, left, "%c", info->params.host_bus_type[i]);
136
} else {
137
p += scnprintf(p, left, " ");
138
}
139
}
140
141
if (!strncmp(info->params.host_bus_type, "ISA", 3)) {
142
p += scnprintf(p, left, "\tbase_address: %x\n",
143
info->params.interface_path.isa.base_address);
144
} else if (!strncmp(info->params.host_bus_type, "PCIX", 4) ||
145
!strncmp(info->params.host_bus_type, "PCI", 3) ||
146
!strncmp(info->params.host_bus_type, "XPRS", 4)) {
147
p += scnprintf(p, left,
148
"\t%02x:%02x.%d channel: %u\n",
149
info->params.interface_path.pci.bus,
150
info->params.interface_path.pci.slot,
151
info->params.interface_path.pci.function,
152
info->params.interface_path.pci.channel);
153
} else if (!strncmp(info->params.host_bus_type, "IBND", 4) ||
154
!strncmp(info->params.host_bus_type, "HTPT", 4)) {
155
p += scnprintf(p, left,
156
"\tTBD: %llx\n",
157
info->params.interface_path.ibnd.reserved);
158
159
} else {
160
p += scnprintf(p, left, "\tunknown: %llx\n",
161
info->params.interface_path.unknown.reserved);
162
}
163
return (p - buf);
164
}
165
166
static ssize_t
167
edd_show_interface(struct edd_device *edev, char *buf)
168
{
169
struct edd_info *info;
170
char *p = buf;
171
int i;
172
173
if (!edev)
174
return -EINVAL;
175
info = edd_dev_get_info(edev);
176
if (!info || !buf)
177
return -EINVAL;
178
179
for (i = 0; i < 8; i++) {
180
if (isprint(info->params.interface_type[i])) {
181
p += scnprintf(p, left, "%c", info->params.interface_type[i]);
182
} else {
183
p += scnprintf(p, left, " ");
184
}
185
}
186
if (!strncmp(info->params.interface_type, "ATAPI", 5)) {
187
p += scnprintf(p, left, "\tdevice: %u lun: %u\n",
188
info->params.device_path.atapi.device,
189
info->params.device_path.atapi.lun);
190
} else if (!strncmp(info->params.interface_type, "ATA", 3)) {
191
p += scnprintf(p, left, "\tdevice: %u\n",
192
info->params.device_path.ata.device);
193
} else if (!strncmp(info->params.interface_type, "SCSI", 4)) {
194
p += scnprintf(p, left, "\tid: %u lun: %llu\n",
195
info->params.device_path.scsi.id,
196
info->params.device_path.scsi.lun);
197
} else if (!strncmp(info->params.interface_type, "USB", 3)) {
198
p += scnprintf(p, left, "\tserial_number: %llx\n",
199
info->params.device_path.usb.serial_number);
200
} else if (!strncmp(info->params.interface_type, "1394", 4)) {
201
p += scnprintf(p, left, "\teui: %llx\n",
202
info->params.device_path.i1394.eui);
203
} else if (!strncmp(info->params.interface_type, "FIBRE", 5)) {
204
p += scnprintf(p, left, "\twwid: %llx lun: %llx\n",
205
info->params.device_path.fibre.wwid,
206
info->params.device_path.fibre.lun);
207
} else if (!strncmp(info->params.interface_type, "I2O", 3)) {
208
p += scnprintf(p, left, "\tidentity_tag: %llx\n",
209
info->params.device_path.i2o.identity_tag);
210
} else if (!strncmp(info->params.interface_type, "RAID", 4)) {
211
p += scnprintf(p, left, "\tidentity_tag: %x\n",
212
info->params.device_path.raid.array_number);
213
} else if (!strncmp(info->params.interface_type, "SATA", 4)) {
214
p += scnprintf(p, left, "\tdevice: %u\n",
215
info->params.device_path.sata.device);
216
} else {
217
p += scnprintf(p, left, "\tunknown: %llx %llx\n",
218
info->params.device_path.unknown.reserved1,
219
info->params.device_path.unknown.reserved2);
220
}
221
222
return (p - buf);
223
}
224
225
/**
226
* edd_show_raw_data() - copies raw data to buffer for userspace to parse
227
* @edev: target edd_device
228
* @buf: output buffer
229
*
230
* Returns: number of bytes written, or -EINVAL on failure
231
*/
232
static ssize_t
233
edd_show_raw_data(struct edd_device *edev, char *buf)
234
{
235
struct edd_info *info;
236
ssize_t len = sizeof (info->params);
237
if (!edev)
238
return -EINVAL;
239
info = edd_dev_get_info(edev);
240
if (!info || !buf)
241
return -EINVAL;
242
243
if (!(info->params.key == 0xBEDD || info->params.key == 0xDDBE))
244
len = info->params.length;
245
246
/* In case of buggy BIOSs */
247
if (len > (sizeof(info->params)))
248
len = sizeof(info->params);
249
250
memcpy(buf, &info->params, len);
251
return len;
252
}
253
254
static ssize_t
255
edd_show_version(struct edd_device *edev, char *buf)
256
{
257
struct edd_info *info;
258
char *p = buf;
259
if (!edev)
260
return -EINVAL;
261
info = edd_dev_get_info(edev);
262
if (!info || !buf)
263
return -EINVAL;
264
265
p += scnprintf(p, left, "0x%02x\n", info->version);
266
return (p - buf);
267
}
268
269
static ssize_t
270
edd_show_mbr_signature(struct edd_device *edev, char *buf)
271
{
272
char *p = buf;
273
p += scnprintf(p, left, "0x%08x\n", edev->mbr_signature);
274
return (p - buf);
275
}
276
277
static ssize_t
278
edd_show_extensions(struct edd_device *edev, char *buf)
279
{
280
struct edd_info *info;
281
char *p = buf;
282
if (!edev)
283
return -EINVAL;
284
info = edd_dev_get_info(edev);
285
if (!info || !buf)
286
return -EINVAL;
287
288
if (info->interface_support & EDD_EXT_FIXED_DISK_ACCESS) {
289
p += scnprintf(p, left, "Fixed disk access\n");
290
}
291
if (info->interface_support & EDD_EXT_DEVICE_LOCKING_AND_EJECTING) {
292
p += scnprintf(p, left, "Device locking and ejecting\n");
293
}
294
if (info->interface_support & EDD_EXT_ENHANCED_DISK_DRIVE_SUPPORT) {
295
p += scnprintf(p, left, "Enhanced Disk Drive support\n");
296
}
297
if (info->interface_support & EDD_EXT_64BIT_EXTENSIONS) {
298
p += scnprintf(p, left, "64-bit extensions\n");
299
}
300
return (p - buf);
301
}
302
303
static ssize_t
304
edd_show_info_flags(struct edd_device *edev, char *buf)
305
{
306
struct edd_info *info;
307
char *p = buf;
308
if (!edev)
309
return -EINVAL;
310
info = edd_dev_get_info(edev);
311
if (!info || !buf)
312
return -EINVAL;
313
314
if (info->params.info_flags & EDD_INFO_DMA_BOUNDARY_ERROR_TRANSPARENT)
315
p += scnprintf(p, left, "DMA boundary error transparent\n");
316
if (info->params.info_flags & EDD_INFO_GEOMETRY_VALID)
317
p += scnprintf(p, left, "geometry valid\n");
318
if (info->params.info_flags & EDD_INFO_REMOVABLE)
319
p += scnprintf(p, left, "removable\n");
320
if (info->params.info_flags & EDD_INFO_WRITE_VERIFY)
321
p += scnprintf(p, left, "write verify\n");
322
if (info->params.info_flags & EDD_INFO_MEDIA_CHANGE_NOTIFICATION)
323
p += scnprintf(p, left, "media change notification\n");
324
if (info->params.info_flags & EDD_INFO_LOCKABLE)
325
p += scnprintf(p, left, "lockable\n");
326
if (info->params.info_flags & EDD_INFO_NO_MEDIA_PRESENT)
327
p += scnprintf(p, left, "no media present\n");
328
if (info->params.info_flags & EDD_INFO_USE_INT13_FN50)
329
p += scnprintf(p, left, "use int13 fn50\n");
330
return (p - buf);
331
}
332
333
static ssize_t
334
edd_show_legacy_max_cylinder(struct edd_device *edev, char *buf)
335
{
336
struct edd_info *info;
337
char *p = buf;
338
if (!edev)
339
return -EINVAL;
340
info = edd_dev_get_info(edev);
341
if (!info || !buf)
342
return -EINVAL;
343
344
p += scnprintf(p, left, "%u\n", info->legacy_max_cylinder);
345
return (p - buf);
346
}
347
348
static ssize_t
349
edd_show_legacy_max_head(struct edd_device *edev, char *buf)
350
{
351
struct edd_info *info;
352
char *p = buf;
353
if (!edev)
354
return -EINVAL;
355
info = edd_dev_get_info(edev);
356
if (!info || !buf)
357
return -EINVAL;
358
359
p += scnprintf(p, left, "%u\n", info->legacy_max_head);
360
return (p - buf);
361
}
362
363
static ssize_t
364
edd_show_legacy_sectors_per_track(struct edd_device *edev, char *buf)
365
{
366
struct edd_info *info;
367
char *p = buf;
368
if (!edev)
369
return -EINVAL;
370
info = edd_dev_get_info(edev);
371
if (!info || !buf)
372
return -EINVAL;
373
374
p += scnprintf(p, left, "%u\n", info->legacy_sectors_per_track);
375
return (p - buf);
376
}
377
378
static ssize_t
379
edd_show_default_cylinders(struct edd_device *edev, char *buf)
380
{
381
struct edd_info *info;
382
char *p = buf;
383
if (!edev)
384
return -EINVAL;
385
info = edd_dev_get_info(edev);
386
if (!info || !buf)
387
return -EINVAL;
388
389
p += scnprintf(p, left, "%u\n", info->params.num_default_cylinders);
390
return (p - buf);
391
}
392
393
static ssize_t
394
edd_show_default_heads(struct edd_device *edev, char *buf)
395
{
396
struct edd_info *info;
397
char *p = buf;
398
if (!edev)
399
return -EINVAL;
400
info = edd_dev_get_info(edev);
401
if (!info || !buf)
402
return -EINVAL;
403
404
p += scnprintf(p, left, "%u\n", info->params.num_default_heads);
405
return (p - buf);
406
}
407
408
static ssize_t
409
edd_show_default_sectors_per_track(struct edd_device *edev, char *buf)
410
{
411
struct edd_info *info;
412
char *p = buf;
413
if (!edev)
414
return -EINVAL;
415
info = edd_dev_get_info(edev);
416
if (!info || !buf)
417
return -EINVAL;
418
419
p += scnprintf(p, left, "%u\n", info->params.sectors_per_track);
420
return (p - buf);
421
}
422
423
static ssize_t
424
edd_show_sectors(struct edd_device *edev, char *buf)
425
{
426
struct edd_info *info;
427
char *p = buf;
428
if (!edev)
429
return -EINVAL;
430
info = edd_dev_get_info(edev);
431
if (!info || !buf)
432
return -EINVAL;
433
434
p += scnprintf(p, left, "%llu\n", info->params.number_of_sectors);
435
return (p - buf);
436
}
437
438
439
/*
440
* Some device instances may not have all the above attributes,
441
* or the attribute values may be meaningless (i.e. if
442
* the device is < EDD 3.0, it won't have host_bus and interface
443
* information), so don't bother making files for them. Likewise
444
* if the default_{cylinders,heads,sectors_per_track} values
445
* are zero, the BIOS doesn't provide sane values, don't bother
446
* creating files for them either.
447
*/
448
449
static int
450
edd_has_legacy_max_cylinder(struct edd_device *edev)
451
{
452
struct edd_info *info;
453
if (!edev)
454
return 0;
455
info = edd_dev_get_info(edev);
456
if (!info)
457
return 0;
458
return info->legacy_max_cylinder > 0;
459
}
460
461
static int
462
edd_has_legacy_max_head(struct edd_device *edev)
463
{
464
struct edd_info *info;
465
if (!edev)
466
return 0;
467
info = edd_dev_get_info(edev);
468
if (!info)
469
return 0;
470
return info->legacy_max_head > 0;
471
}
472
473
static int
474
edd_has_legacy_sectors_per_track(struct edd_device *edev)
475
{
476
struct edd_info *info;
477
if (!edev)
478
return 0;
479
info = edd_dev_get_info(edev);
480
if (!info)
481
return 0;
482
return info->legacy_sectors_per_track > 0;
483
}
484
485
static int
486
edd_has_default_cylinders(struct edd_device *edev)
487
{
488
struct edd_info *info;
489
if (!edev)
490
return 0;
491
info = edd_dev_get_info(edev);
492
if (!info)
493
return 0;
494
return info->params.num_default_cylinders > 0;
495
}
496
497
static int
498
edd_has_default_heads(struct edd_device *edev)
499
{
500
struct edd_info *info;
501
if (!edev)
502
return 0;
503
info = edd_dev_get_info(edev);
504
if (!info)
505
return 0;
506
return info->params.num_default_heads > 0;
507
}
508
509
static int
510
edd_has_default_sectors_per_track(struct edd_device *edev)
511
{
512
struct edd_info *info;
513
if (!edev)
514
return 0;
515
info = edd_dev_get_info(edev);
516
if (!info)
517
return 0;
518
return info->params.sectors_per_track > 0;
519
}
520
521
static int
522
edd_has_edd30(struct edd_device *edev)
523
{
524
struct edd_info *info;
525
int i;
526
u8 csum = 0;
527
528
if (!edev)
529
return 0;
530
info = edd_dev_get_info(edev);
531
if (!info)
532
return 0;
533
534
if (!(info->params.key == 0xBEDD || info->params.key == 0xDDBE)) {
535
return 0;
536
}
537
538
539
/* We support only T13 spec */
540
if (info->params.device_path_info_length != 44)
541
return 0;
542
543
for (i = 30; i < info->params.device_path_info_length + 30; i++)
544
csum += *(((u8 *)&info->params) + i);
545
546
if (csum)
547
return 0;
548
549
return 1;
550
}
551
552
553
static EDD_DEVICE_ATTR(raw_data, 0444, edd_show_raw_data, edd_has_edd_info);
554
static EDD_DEVICE_ATTR(version, 0444, edd_show_version, edd_has_edd_info);
555
static EDD_DEVICE_ATTR(extensions, 0444, edd_show_extensions, edd_has_edd_info);
556
static EDD_DEVICE_ATTR(info_flags, 0444, edd_show_info_flags, edd_has_edd_info);
557
static EDD_DEVICE_ATTR(sectors, 0444, edd_show_sectors, edd_has_edd_info);
558
static EDD_DEVICE_ATTR(legacy_max_cylinder, 0444,
559
edd_show_legacy_max_cylinder,
560
edd_has_legacy_max_cylinder);
561
static EDD_DEVICE_ATTR(legacy_max_head, 0444, edd_show_legacy_max_head,
562
edd_has_legacy_max_head);
563
static EDD_DEVICE_ATTR(legacy_sectors_per_track, 0444,
564
edd_show_legacy_sectors_per_track,
565
edd_has_legacy_sectors_per_track);
566
static EDD_DEVICE_ATTR(default_cylinders, 0444, edd_show_default_cylinders,
567
edd_has_default_cylinders);
568
static EDD_DEVICE_ATTR(default_heads, 0444, edd_show_default_heads,
569
edd_has_default_heads);
570
static EDD_DEVICE_ATTR(default_sectors_per_track, 0444,
571
edd_show_default_sectors_per_track,
572
edd_has_default_sectors_per_track);
573
static EDD_DEVICE_ATTR(interface, 0444, edd_show_interface, edd_has_edd30);
574
static EDD_DEVICE_ATTR(host_bus, 0444, edd_show_host_bus, edd_has_edd30);
575
static EDD_DEVICE_ATTR(mbr_signature, 0444, edd_show_mbr_signature, edd_has_mbr_signature);
576
577
/* These attributes are conditional and only added for some devices. */
578
static struct edd_attribute * edd_attrs[] = {
579
&edd_attr_raw_data,
580
&edd_attr_version,
581
&edd_attr_extensions,
582
&edd_attr_info_flags,
583
&edd_attr_sectors,
584
&edd_attr_legacy_max_cylinder,
585
&edd_attr_legacy_max_head,
586
&edd_attr_legacy_sectors_per_track,
587
&edd_attr_default_cylinders,
588
&edd_attr_default_heads,
589
&edd_attr_default_sectors_per_track,
590
&edd_attr_interface,
591
&edd_attr_host_bus,
592
&edd_attr_mbr_signature,
593
NULL,
594
};
595
596
/**
597
* edd_release - free edd structure
598
* @kobj: kobject of edd structure
599
*
600
* This is called when the refcount of the edd structure
601
* reaches 0. This should happen right after we unregister,
602
* but just in case, we use the release callback anyway.
603
*/
604
605
static void edd_release(struct kobject * kobj)
606
{
607
struct edd_device * dev = to_edd_device(kobj);
608
kfree(dev);
609
}
610
611
static const struct kobj_type edd_ktype = {
612
.release = edd_release,
613
.sysfs_ops = &edd_attr_ops,
614
};
615
616
static struct kset *edd_kset;
617
618
619
/**
620
* edd_dev_is_type() - is this EDD device a 'type' device?
621
* @edev: target edd_device
622
* @type: a host bus or interface identifier string per the EDD spec
623
*
624
* Returns 1 (TRUE) if it is a 'type' device, 0 otherwise.
625
*/
626
static int
627
edd_dev_is_type(struct edd_device *edev, const char *type)
628
{
629
struct edd_info *info;
630
if (!edev)
631
return 0;
632
info = edd_dev_get_info(edev);
633
634
if (type && info) {
635
if (!strncmp(info->params.host_bus_type, type, strlen(type)) ||
636
!strncmp(info->params.interface_type, type, strlen(type)))
637
return 1;
638
}
639
return 0;
640
}
641
642
/**
643
* edd_get_pci_dev() - finds pci_dev that matches edev
644
* @edev: edd_device
645
*
646
* Returns pci_dev if found, or NULL
647
*/
648
static struct pci_dev *
649
edd_get_pci_dev(struct edd_device *edev)
650
{
651
struct edd_info *info = edd_dev_get_info(edev);
652
653
if (edd_dev_is_type(edev, "PCI") || edd_dev_is_type(edev, "XPRS")) {
654
return pci_get_domain_bus_and_slot(0,
655
info->params.interface_path.pci.bus,
656
PCI_DEVFN(info->params.interface_path.pci.slot,
657
info->params.interface_path.pci.function));
658
}
659
return NULL;
660
}
661
662
static int
663
edd_create_symlink_to_pcidev(struct edd_device *edev)
664
{
665
666
struct pci_dev *pci_dev = edd_get_pci_dev(edev);
667
int ret;
668
if (!pci_dev)
669
return 1;
670
ret = sysfs_create_link(&edev->kobj,&pci_dev->dev.kobj,"pci_dev");
671
pci_dev_put(pci_dev);
672
return ret;
673
}
674
675
static inline void
676
edd_device_unregister(struct edd_device *edev)
677
{
678
kobject_put(&edev->kobj);
679
}
680
681
static void edd_populate_dir(struct edd_device * edev)
682
{
683
struct edd_attribute * attr;
684
int error = 0;
685
int i;
686
687
for (i = 0; (attr = edd_attrs[i]) && !error; i++) {
688
if (!attr->test || attr->test(edev))
689
error = sysfs_create_file(&edev->kobj,&attr->attr);
690
}
691
692
if (!error) {
693
edd_create_symlink_to_pcidev(edev);
694
}
695
}
696
697
static int
698
edd_device_register(struct edd_device *edev, int i)
699
{
700
int error;
701
702
if (!edev)
703
return 1;
704
edd_dev_set_info(edev, i);
705
edev->kobj.kset = edd_kset;
706
error = kobject_init_and_add(&edev->kobj, &edd_ktype, NULL,
707
"int13_dev%02x", 0x80 + i);
708
if (!error) {
709
edd_populate_dir(edev);
710
kobject_uevent(&edev->kobj, KOBJ_ADD);
711
}
712
return error;
713
}
714
715
static inline int edd_num_devices(void)
716
{
717
return max_t(unsigned char,
718
min_t(unsigned char, EDD_MBR_SIG_MAX, edd.mbr_signature_nr),
719
min_t(unsigned char, EDDMAXNR, edd.edd_info_nr));
720
}
721
722
/**
723
* edd_init() - creates sysfs tree of EDD data
724
*/
725
static int __init
726
edd_init(void)
727
{
728
int i;
729
int rc=0;
730
struct edd_device *edev;
731
732
if (!edd_num_devices())
733
return -ENODEV;
734
735
printk(KERN_INFO "BIOS EDD facility v%s %s, %d devices found\n",
736
EDD_VERSION, EDD_DATE, edd_num_devices());
737
738
edd_kset = kset_create_and_add("edd", NULL, firmware_kobj);
739
if (!edd_kset)
740
return -ENOMEM;
741
742
for (i = 0; i < edd_num_devices(); i++) {
743
edev = kzalloc(sizeof (*edev), GFP_KERNEL);
744
if (!edev) {
745
rc = -ENOMEM;
746
goto out;
747
}
748
749
rc = edd_device_register(edev, i);
750
if (rc) {
751
kfree(edev);
752
goto out;
753
}
754
edd_devices[i] = edev;
755
}
756
757
return 0;
758
759
out:
760
while (--i >= 0)
761
edd_device_unregister(edd_devices[i]);
762
kset_unregister(edd_kset);
763
return rc;
764
}
765
766
static void __exit
767
edd_exit(void)
768
{
769
int i;
770
struct edd_device *edev;
771
772
for (i = 0; i < edd_num_devices(); i++) {
773
if ((edev = edd_devices[i]))
774
edd_device_unregister(edev);
775
}
776
kset_unregister(edd_kset);
777
}
778
779
late_initcall(edd_init);
780
module_exit(edd_exit);
781
782