diff options
author | Peter Jones <pjones@redhat.com> | 2010-02-25 15:37:17 -0500 |
---|---|---|
committer | Konrad Rzeszutek Wilk <konrad@kernel.org> | 2010-05-11 13:02:23 -0400 |
commit | 4e639fdf0d0d745648aa62228ab8a0d9c03a563f (patch) | |
tree | c6cb611ffc6f3e17e10ca3f39ac00f0e39b1ee4b | |
parent | 94b849aaf6e22ab7bf54b0d0377a882d4892396d (diff) |
ibft: Update iBFT handling for v1.03 of the spec.
- Use struct acpi_table_ibft instead of struct ibft_table_header
- Don't do reserve_ibft_region() on UEFI machines (section 1.4.3.1)
- If ibft_addr isn't initialized when ibft_init() is called, check for
ACPI-based tables.
- Fix compiler error when CONFIG_ACPI is not defined.
Signed-off-by: Konrad Rzeszutek Wilk <konrad@kernel.org>
Signed-off-by: Peter Jones <pjones@redhat.com>
Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
-rw-r--r-- | drivers/firmware/iscsi_ibft.c | 30 | ||||
-rw-r--r-- | drivers/firmware/iscsi_ibft_find.c | 35 | ||||
-rw-r--r-- | include/linux/iscsi_ibft.h | 12 |
3 files changed, 50 insertions, 27 deletions
diff --git a/drivers/firmware/iscsi_ibft.c b/drivers/firmware/iscsi_ibft.c index ed2801c378de..b3ab24f9d78f 100644 --- a/drivers/firmware/iscsi_ibft.c +++ b/drivers/firmware/iscsi_ibft.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright 2007 Red Hat, Inc. | 2 | * Copyright 2007-2010 Red Hat, Inc. |
3 | * by Peter Jones <pjones@redhat.com> | 3 | * by Peter Jones <pjones@redhat.com> |
4 | * Copyright 2008 IBM, Inc. | 4 | * Copyright 2008 IBM, Inc. |
5 | * by Konrad Rzeszutek <konradr@linux.vnet.ibm.com> | 5 | * by Konrad Rzeszutek <konradr@linux.vnet.ibm.com> |
@@ -19,6 +19,9 @@ | |||
19 | * | 19 | * |
20 | * Changelog: | 20 | * Changelog: |
21 | * | 21 | * |
22 | * 06 Jan 2010 - Peter Jones <pjones@redhat.com> | ||
23 | * New changelog entries are in the git log from now on. Not here. | ||
24 | * | ||
22 | * 14 Mar 2008 - Konrad Rzeszutek <ketuzsezr@darnok.org> | 25 | * 14 Mar 2008 - Konrad Rzeszutek <ketuzsezr@darnok.org> |
23 | * Updated comments and copyrights. (v0.4.9) | 26 | * Updated comments and copyrights. (v0.4.9) |
24 | * | 27 | * |
@@ -78,9 +81,10 @@ | |||
78 | #include <linux/stat.h> | 81 | #include <linux/stat.h> |
79 | #include <linux/string.h> | 82 | #include <linux/string.h> |
80 | #include <linux/types.h> | 83 | #include <linux/types.h> |
84 | #include <linux/acpi.h> | ||
81 | 85 | ||
82 | #define IBFT_ISCSI_VERSION "0.4.9" | 86 | #define IBFT_ISCSI_VERSION "0.5.0" |
83 | #define IBFT_ISCSI_DATE "2008-Mar-14" | 87 | #define IBFT_ISCSI_DATE "2010-Feb-25" |
84 | 88 | ||
85 | MODULE_AUTHOR("Peter Jones <pjones@redhat.com> and \ | 89 | MODULE_AUTHOR("Peter Jones <pjones@redhat.com> and \ |
86 | Konrad Rzeszutek <ketuzsezr@darnok.org>"); | 90 | Konrad Rzeszutek <ketuzsezr@darnok.org>"); |
@@ -238,7 +242,7 @@ static const char *ibft_initiator_properties[] = | |||
238 | */ | 242 | */ |
239 | 243 | ||
240 | struct ibft_kobject { | 244 | struct ibft_kobject { |
241 | struct ibft_table_header *header; | 245 | struct acpi_table_ibft *header; |
242 | union { | 246 | union { |
243 | struct ibft_initiator *initiator; | 247 | struct ibft_initiator *initiator; |
244 | struct ibft_nic *nic; | 248 | struct ibft_nic *nic; |
@@ -536,12 +540,13 @@ static int __init ibft_check_device(void) | |||
536 | u8 *pos; | 540 | u8 *pos; |
537 | u8 csum = 0; | 541 | u8 csum = 0; |
538 | 542 | ||
539 | len = ibft_addr->length; | 543 | len = ibft_addr->header.length; |
540 | 544 | ||
541 | /* Sanity checking of iBFT. */ | 545 | /* Sanity checking of iBFT. */ |
542 | if (ibft_addr->revision != 1) { | 546 | if (ibft_addr->header.revision != 1) { |
543 | printk(KERN_ERR "iBFT module supports only revision 1, " \ | 547 | printk(KERN_ERR "iBFT module supports only revision 1, " \ |
544 | "while this is %d.\n", ibft_addr->revision); | 548 | "while this is %d.\n", |
549 | ibft_addr->header.revision); | ||
545 | return -ENOENT; | 550 | return -ENOENT; |
546 | } | 551 | } |
547 | for (pos = (u8 *)ibft_addr; pos < (u8 *)ibft_addr + len; pos++) | 552 | for (pos = (u8 *)ibft_addr; pos < (u8 *)ibft_addr + len; pos++) |
@@ -558,7 +563,7 @@ static int __init ibft_check_device(void) | |||
558 | /* | 563 | /* |
559 | * Helper function for ibft_register_kobjects. | 564 | * Helper function for ibft_register_kobjects. |
560 | */ | 565 | */ |
561 | static int __init ibft_create_kobject(struct ibft_table_header *header, | 566 | static int __init ibft_create_kobject(struct acpi_table_ibft *header, |
562 | struct ibft_hdr *hdr, | 567 | struct ibft_hdr *hdr, |
563 | struct list_head *list) | 568 | struct list_head *list) |
564 | { | 569 | { |
@@ -596,7 +601,7 @@ static int __init ibft_create_kobject(struct ibft_table_header *header, | |||
596 | default: | 601 | default: |
597 | printk(KERN_ERR "iBFT has unknown structure type (%d). " \ | 602 | printk(KERN_ERR "iBFT has unknown structure type (%d). " \ |
598 | "Report this bug to %.6s!\n", hdr->id, | 603 | "Report this bug to %.6s!\n", hdr->id, |
599 | header->oem_id); | 604 | header->header.oem_id); |
600 | rc = 1; | 605 | rc = 1; |
601 | break; | 606 | break; |
602 | } | 607 | } |
@@ -649,7 +654,7 @@ out_invalid_struct: | |||
649 | * found add them on the passed-in list. We do not support the other | 654 | * found add them on the passed-in list. We do not support the other |
650 | * fields at this point, so they are skipped. | 655 | * fields at this point, so they are skipped. |
651 | */ | 656 | */ |
652 | static int __init ibft_register_kobjects(struct ibft_table_header *header, | 657 | static int __init ibft_register_kobjects(struct acpi_table_ibft *header, |
653 | struct list_head *list) | 658 | struct list_head *list) |
654 | { | 659 | { |
655 | struct ibft_control *control = NULL; | 660 | struct ibft_control *control = NULL; |
@@ -660,7 +665,7 @@ static int __init ibft_register_kobjects(struct ibft_table_header *header, | |||
660 | 665 | ||
661 | control = (void *)header + sizeof(*header); | 666 | control = (void *)header + sizeof(*header); |
662 | end = (void *)control + control->hdr.length; | 667 | end = (void *)control + control->hdr.length; |
663 | eot_offset = (void *)header + header->length - (void *)control; | 668 | eot_offset = (void *)header + header->header.length - (void *)control; |
664 | rc = ibft_verify_hdr("control", (struct ibft_hdr *)control, id_control, | 669 | rc = ibft_verify_hdr("control", (struct ibft_hdr *)control, id_control, |
665 | sizeof(*control)); | 670 | sizeof(*control)); |
666 | 671 | ||
@@ -672,7 +677,8 @@ static int __init ibft_register_kobjects(struct ibft_table_header *header, | |||
672 | } | 677 | } |
673 | for (ptr = &control->initiator_off; ptr < end; ptr += sizeof(u16)) { | 678 | for (ptr = &control->initiator_off; ptr < end; ptr += sizeof(u16)) { |
674 | offset = *(u16 *)ptr; | 679 | offset = *(u16 *)ptr; |
675 | if (offset && offset < header->length && offset < eot_offset) { | 680 | if (offset && offset < header->header.length && |
681 | offset < eot_offset) { | ||
676 | rc = ibft_create_kobject(header, | 682 | rc = ibft_create_kobject(header, |
677 | (void *)header + offset, | 683 | (void *)header + offset, |
678 | list); | 684 | list); |
diff --git a/drivers/firmware/iscsi_ibft_find.c b/drivers/firmware/iscsi_ibft_find.c index d6470ef36e4a..dd85555d3296 100644 --- a/drivers/firmware/iscsi_ibft_find.c +++ b/drivers/firmware/iscsi_ibft_find.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright 2007 Red Hat, Inc. | 2 | * Copyright 2007-2010 Red Hat, Inc. |
3 | * by Peter Jones <pjones@redhat.com> | 3 | * by Peter Jones <pjones@redhat.com> |
4 | * Copyright 2007 IBM, Inc. | 4 | * Copyright 2007 IBM, Inc. |
5 | * by Konrad Rzeszutek <konradr@linux.vnet.ibm.com> | 5 | * by Konrad Rzeszutek <konradr@linux.vnet.ibm.com> |
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/blkdev.h> | 22 | #include <linux/blkdev.h> |
23 | #include <linux/ctype.h> | 23 | #include <linux/ctype.h> |
24 | #include <linux/device.h> | 24 | #include <linux/device.h> |
25 | #include <linux/efi.h> | ||
25 | #include <linux/err.h> | 26 | #include <linux/err.h> |
26 | #include <linux/init.h> | 27 | #include <linux/init.h> |
27 | #include <linux/limits.h> | 28 | #include <linux/limits.h> |
@@ -30,13 +31,15 @@ | |||
30 | #include <linux/stat.h> | 31 | #include <linux/stat.h> |
31 | #include <linux/string.h> | 32 | #include <linux/string.h> |
32 | #include <linux/types.h> | 33 | #include <linux/types.h> |
34 | #include <linux/acpi.h> | ||
35 | #include <linux/iscsi_ibft.h> | ||
33 | 36 | ||
34 | #include <asm/mmzone.h> | 37 | #include <asm/mmzone.h> |
35 | 38 | ||
36 | /* | 39 | /* |
37 | * Physical location of iSCSI Boot Format Table. | 40 | * Physical location of iSCSI Boot Format Table. |
38 | */ | 41 | */ |
39 | struct ibft_table_header *ibft_addr; | 42 | struct acpi_table_ibft *ibft_addr; |
40 | EXPORT_SYMBOL_GPL(ibft_addr); | 43 | EXPORT_SYMBOL_GPL(ibft_addr); |
41 | 44 | ||
42 | #define IBFT_SIGN "iBFT" | 45 | #define IBFT_SIGN "iBFT" |
@@ -46,6 +49,13 @@ EXPORT_SYMBOL_GPL(ibft_addr); | |||
46 | #define VGA_MEM 0xA0000 /* VGA buffer */ | 49 | #define VGA_MEM 0xA0000 /* VGA buffer */ |
47 | #define VGA_SIZE 0x20000 /* 128kB */ | 50 | #define VGA_SIZE 0x20000 /* 128kB */ |
48 | 51 | ||
52 | #ifdef CONFIG_ACPI | ||
53 | static int __init acpi_find_ibft(struct acpi_table_header *header) | ||
54 | { | ||
55 | ibft_addr = (struct acpi_table_ibft *)header; | ||
56 | return 0; | ||
57 | } | ||
58 | #endif /* CONFIG_ACPI */ | ||
49 | 59 | ||
50 | /* | 60 | /* |
51 | * Routine used to find the iSCSI Boot Format Table. The logical | 61 | * Routine used to find the iSCSI Boot Format Table. The logical |
@@ -59,6 +69,11 @@ unsigned long __init find_ibft_region(unsigned long *sizep) | |||
59 | 69 | ||
60 | ibft_addr = NULL; | 70 | ibft_addr = NULL; |
61 | 71 | ||
72 | /* iBFT 1.03 section 1.4.3.1 mandates that UEFI machines will | ||
73 | * only use ACPI for this */ | ||
74 | if (efi_enabled) | ||
75 | return 0; | ||
76 | |||
62 | for (pos = IBFT_START; pos < IBFT_END; pos += 16) { | 77 | for (pos = IBFT_START; pos < IBFT_END; pos += 16) { |
63 | /* The table can't be inside the VGA BIOS reserved space, | 78 | /* The table can't be inside the VGA BIOS reserved space, |
64 | * so skip that area */ | 79 | * so skip that area */ |
@@ -72,14 +87,24 @@ unsigned long __init find_ibft_region(unsigned long *sizep) | |||
72 | /* if the length of the table extends past 1M, | 87 | /* if the length of the table extends past 1M, |
73 | * the table cannot be valid. */ | 88 | * the table cannot be valid. */ |
74 | if (pos + len <= (IBFT_END-1)) { | 89 | if (pos + len <= (IBFT_END-1)) { |
75 | ibft_addr = (struct ibft_table_header *)virt; | 90 | ibft_addr = (struct acpi_table_ibft *)virt; |
76 | break; | 91 | break; |
77 | } | 92 | } |
78 | } | 93 | } |
79 | } | 94 | } |
95 | #ifdef CONFIG_ACPI | ||
96 | /* | ||
97 | * One spec says "IBFT", the other says "iBFT". We have to check | ||
98 | * for both. | ||
99 | */ | ||
100 | if (!ibft_addr) | ||
101 | acpi_table_parse(ACPI_SIG_IBFT, acpi_find_ibft); | ||
102 | if (!ibft_addr) | ||
103 | acpi_table_parse("iBFT", acpi_find_ibft); | ||
104 | #endif /* CONFIG_ACPI */ | ||
80 | if (ibft_addr) { | 105 | if (ibft_addr) { |
81 | *sizep = PAGE_ALIGN(len); | 106 | *sizep = PAGE_ALIGN(ibft_addr->header.length); |
82 | return pos; | 107 | return (u64)isa_virt_to_bus(ibft_addr); |
83 | } | 108 | } |
84 | 109 | ||
85 | *sizep = 0; | 110 | *sizep = 0; |
diff --git a/include/linux/iscsi_ibft.h b/include/linux/iscsi_ibft.h index d2e4042f8f5e..8ba7e5b9d62c 100644 --- a/include/linux/iscsi_ibft.h +++ b/include/linux/iscsi_ibft.h | |||
@@ -21,21 +21,13 @@ | |||
21 | #ifndef ISCSI_IBFT_H | 21 | #ifndef ISCSI_IBFT_H |
22 | #define ISCSI_IBFT_H | 22 | #define ISCSI_IBFT_H |
23 | 23 | ||
24 | struct ibft_table_header { | 24 | #include <acpi/acpi.h> |
25 | char signature[4]; | ||
26 | u32 length; | ||
27 | u8 revision; | ||
28 | u8 checksum; | ||
29 | char oem_id[6]; | ||
30 | char oem_table_id[8]; | ||
31 | char reserved[24]; | ||
32 | } __attribute__((__packed__)); | ||
33 | 25 | ||
34 | /* | 26 | /* |
35 | * Logical location of iSCSI Boot Format Table. | 27 | * Logical location of iSCSI Boot Format Table. |
36 | * If the value is NULL there is no iBFT on the machine. | 28 | * If the value is NULL there is no iBFT on the machine. |
37 | */ | 29 | */ |
38 | extern struct ibft_table_header *ibft_addr; | 30 | extern struct acpi_table_ibft *ibft_addr; |
39 | 31 | ||
40 | /* | 32 | /* |
41 | * Routine used to find and reserve the iSCSI Boot Format Table. The | 33 | * Routine used to find and reserve the iSCSI Boot Format Table. The |