GNU Linux-libre 5.19-rc6-gnu
[releases.git] / drivers / firmware / edd.c
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 <Matt_Domsch@dell.com>
6  *  disk signature by Matt Domsch, Andrew Wilks, and Sandeep K. Shandilya
7  *  legacy CHS by Patrick J. LoPresti <patl@users.sourceforge.net>
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 <Matt_Domsch@Dell.com>");
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 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);