xref: /titanic_53/usr/src/uts/i86pc/os/ibft.c (revision 6cefaae1e90a413ba01560575bb3998e1a3df40e)
1*6cefaae1SJack Meng /*
2*6cefaae1SJack Meng  * CDDL HEADER START
3*6cefaae1SJack Meng  *
4*6cefaae1SJack Meng  * The contents of this file are subject to the terms of the
5*6cefaae1SJack Meng  * Common Development and Distribution License (the "License").
6*6cefaae1SJack Meng  * You may not use this file except in compliance with the License.
7*6cefaae1SJack Meng  *
8*6cefaae1SJack Meng  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*6cefaae1SJack Meng  * or http://www.opensolaris.org/os/licensing.
10*6cefaae1SJack Meng  * See the License for the specific language governing permissions
11*6cefaae1SJack Meng  * and limitations under the License.
12*6cefaae1SJack Meng  *
13*6cefaae1SJack Meng  * When distributing Covered Code, include this CDDL HEADER in each
14*6cefaae1SJack Meng  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*6cefaae1SJack Meng  * If applicable, add the following below this CDDL HEADER, with the
16*6cefaae1SJack Meng  * fields enclosed by brackets "[]" replaced with your own identifying
17*6cefaae1SJack Meng  * information: Portions Copyright [yyyy] [name of copyright owner]
18*6cefaae1SJack Meng  *
19*6cefaae1SJack Meng  * CDDL HEADER END
20*6cefaae1SJack Meng  */
21*6cefaae1SJack Meng 
22*6cefaae1SJack Meng /*
23*6cefaae1SJack Meng  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24*6cefaae1SJack Meng  * Use is subject to license terms.
25*6cefaae1SJack Meng  */
26*6cefaae1SJack Meng 
27*6cefaae1SJack Meng /*
28*6cefaae1SJack Meng  * This is the place to implement ld_ib_props()
29*6cefaae1SJack Meng  * For x86 it is to load iBFT and costruct the global ib props
30*6cefaae1SJack Meng  */
31*6cefaae1SJack Meng 
32*6cefaae1SJack Meng #include <sys/types.h>
33*6cefaae1SJack Meng #include <sys/cmn_err.h>
34*6cefaae1SJack Meng #include <sys/socket.h>
35*6cefaae1SJack Meng #include <netinet/in.h>
36*6cefaae1SJack Meng #include <sys/mman.h>
37*6cefaae1SJack Meng #include <sys/bootprops.h>
38*6cefaae1SJack Meng #include <sys/kmem.h>
39*6cefaae1SJack Meng #include <sys/psm.h>
40*6cefaae1SJack Meng 
41*6cefaae1SJack Meng #ifndef	NULL
42*6cefaae1SJack Meng #define	NULL	0
43*6cefaae1SJack Meng #endif
44*6cefaae1SJack Meng 
45*6cefaae1SJack Meng typedef enum ibft_structure_type {
46*6cefaae1SJack Meng 	Reserved	=	0,
47*6cefaae1SJack Meng 	Control		=	1,
48*6cefaae1SJack Meng 	Initiator	=	2,
49*6cefaae1SJack Meng 	Nic		=	3,
50*6cefaae1SJack Meng 	Target		=	4,
51*6cefaae1SJack Meng 	Extensions	=	5,
52*6cefaae1SJack Meng 	Type_End
53*6cefaae1SJack Meng }ibft_struct_type;
54*6cefaae1SJack Meng 
55*6cefaae1SJack Meng typedef enum _chap_type {
56*6cefaae1SJack Meng 	NO_CHAP		=	0,
57*6cefaae1SJack Meng 	CHAP		=	1,
58*6cefaae1SJack Meng 	Mutual_CHAP	=	2,
59*6cefaae1SJack Meng 	TYPE_UNKNOWN
60*6cefaae1SJack Meng }chap_type;
61*6cefaae1SJack Meng 
62*6cefaae1SJack Meng typedef struct ibft_entry {
63*6cefaae1SJack Meng 	int	af;
64*6cefaae1SJack Meng 	int	e_port;
65*6cefaae1SJack Meng 	char	target_name[224];
66*6cefaae1SJack Meng 	char	target_addr[INET6_ADDRSTRLEN];
67*6cefaae1SJack Meng }ibft_entry_t;
68*6cefaae1SJack Meng 
69*6cefaae1SJack Meng typedef struct iSCSI_ibft_tbl_hdr {
70*6cefaae1SJack Meng 	char	    Signature[4];
71*6cefaae1SJack Meng 	int	    Length;
72*6cefaae1SJack Meng 	char	    Revision;
73*6cefaae1SJack Meng 	char	    Checksum;
74*6cefaae1SJack Meng 	char	    oem_id[6];
75*6cefaae1SJack Meng 	char	    oem_table_id[8];
76*6cefaae1SJack Meng 	char	    Reserved[24];
77*6cefaae1SJack Meng }iscsi_ibft_tbl_hdr_t;
78*6cefaae1SJack Meng 
79*6cefaae1SJack Meng typedef struct iSCSI_ibft_hdr {
80*6cefaae1SJack Meng 	char	    Structure_id;
81*6cefaae1SJack Meng 	char	    Version;
82*6cefaae1SJack Meng 	ushort_t    Length;
83*6cefaae1SJack Meng 	char	    Index;
84*6cefaae1SJack Meng 	char	    Flags;
85*6cefaae1SJack Meng }iscsi_ibft_hdr_t;
86*6cefaae1SJack Meng 
87*6cefaae1SJack Meng typedef struct iSCSI_ibft_control {
88*6cefaae1SJack Meng 	iscsi_ibft_hdr_t    header;
89*6cefaae1SJack Meng 	ushort_t	    Extensions;
90*6cefaae1SJack Meng 	ushort_t	    Initiator_offset;
91*6cefaae1SJack Meng 	ushort_t	    Nic0_offset;
92*6cefaae1SJack Meng 	ushort_t	    Target0_offset;
93*6cefaae1SJack Meng 	ushort_t	    Nic1_offset;
94*6cefaae1SJack Meng 	ushort_t	    Target1_offset;
95*6cefaae1SJack Meng }iscsi_ibft_ctl_t;
96*6cefaae1SJack Meng 
97*6cefaae1SJack Meng typedef struct iSCSI_ibft_initiator {
98*6cefaae1SJack Meng 	iscsi_ibft_hdr_t    header;
99*6cefaae1SJack Meng 	uchar_t		    iSNS_Server[16];
100*6cefaae1SJack Meng 	uchar_t		    SLP_Server[16];
101*6cefaae1SJack Meng 	uchar_t		    Pri_Radius_Server[16];
102*6cefaae1SJack Meng 	uchar_t		    Sec_Radius_Server[16];
103*6cefaae1SJack Meng 	ushort_t	    ini_name_len;
104*6cefaae1SJack Meng 	ushort_t	    ini_name_offset;
105*6cefaae1SJack Meng }iscsi_ibft_initiator_t;
106*6cefaae1SJack Meng 
107*6cefaae1SJack Meng typedef struct iSCSI_ibft_nic {
108*6cefaae1SJack Meng 	iscsi_ibft_hdr_t    header;
109*6cefaae1SJack Meng 	uchar_t		    ip_addr[16];
110*6cefaae1SJack Meng 	char		    Subnet_Mask_Prefix;
111*6cefaae1SJack Meng 	char		    Origin;
112*6cefaae1SJack Meng 	uchar_t		    Gateway[16];
113*6cefaae1SJack Meng 	uchar_t		    Primary_dns[16];
114*6cefaae1SJack Meng 	uchar_t		    Secondary_dns[16];
115*6cefaae1SJack Meng 	uchar_t		    dhcp[16];
116*6cefaae1SJack Meng 	ushort_t	    vlan;
117*6cefaae1SJack Meng 	char		    mac[6];
118*6cefaae1SJack Meng 	ushort_t	    pci_BDF;
119*6cefaae1SJack Meng 	ushort_t	    Hostname_len;
120*6cefaae1SJack Meng 	ushort_t	    Hostname_offset;
121*6cefaae1SJack Meng }iscsi_ibft_nic_t;
122*6cefaae1SJack Meng 
123*6cefaae1SJack Meng typedef struct iSCSI_ibft_target {
124*6cefaae1SJack Meng 	iscsi_ibft_hdr_t    header;
125*6cefaae1SJack Meng 	uchar_t		    ip_addr[16];
126*6cefaae1SJack Meng 	ushort_t	    port;
127*6cefaae1SJack Meng 	uchar_t		    boot_lun[8];
128*6cefaae1SJack Meng 	uchar_t		    chap_type;
129*6cefaae1SJack Meng 	uchar_t		    nic_association;
130*6cefaae1SJack Meng 	ushort_t	    target_name_len;
131*6cefaae1SJack Meng 	ushort_t	    target_name_offset;
132*6cefaae1SJack Meng 	ushort_t	    chap_name_len;
133*6cefaae1SJack Meng 	ushort_t	    chap_name_offset;
134*6cefaae1SJack Meng 	ushort_t	    chap_secret_len;
135*6cefaae1SJack Meng 	ushort_t	    chap_secret_offset;
136*6cefaae1SJack Meng 	ushort_t	    rev_chap_name_len;
137*6cefaae1SJack Meng 	ushort_t	    rev_chap_name_offset;
138*6cefaae1SJack Meng 	ushort_t	    rev_chap_secret_len;
139*6cefaae1SJack Meng 	ushort_t	    rev_chap_secret_offset;
140*6cefaae1SJack Meng }iscsi_ibft_tgt_t;
141*6cefaae1SJack Meng 
142*6cefaae1SJack Meng #define	ISCSI_IBFT_LOWER_ADDR		0x80000	    /* 512K */
143*6cefaae1SJack Meng #define	ISCSI_IBFT_HIGHER_ADDR		0x100000    /* 1024K */
144*6cefaae1SJack Meng #define	ISCSI_IBFT_SIGNATRUE		"iBFT"
145*6cefaae1SJack Meng #define	ISCSI_IBFT_SIGNATURE_LEN	4
146*6cefaae1SJack Meng #define	ISCSI_IBFT_TBL_BUF_LEN		1024
147*6cefaae1SJack Meng #define	ISCSI_IBFT_ALIGNED		16
148*6cefaae1SJack Meng #define	ISCSI_IBFT_CTL_OFFSET		48
149*6cefaae1SJack Meng 
150*6cefaae1SJack Meng #define	IBFT_BLOCK_VALID_YES		0x01	/* bit 0 */
151*6cefaae1SJack Meng #define	IBFT_FIRMWARE_BOOT_SELECTED	0x02	/* bit 1 */
152*6cefaae1SJack Meng #define	IBFT_USE_RADIUS_CHAP		0x04	/* bit 2 */
153*6cefaae1SJack Meng #define	IBFT_USE_GLOBLE			0x04	/* NIC structure */
154*6cefaae1SJack Meng #define	IBFT_USE_RADIUS_RHCAP		0x08	/* bit 3 */
155*6cefaae1SJack Meng 
156*6cefaae1SJack Meng /*
157*6cefaae1SJack Meng  * Currently, we only support initiator offset, NIC0 offset, Target0 offset,
158*6cefaae1SJack Meng  * NIC1 offset and Target1 offset. So the length is 5. If we want to support
159*6cefaae1SJack Meng  * extensions, we should change this number.
160*6cefaae1SJack Meng  */
161*6cefaae1SJack Meng #define	IBFT_OFFSET_BUF_LEN		5
162*6cefaae1SJack Meng #define	IPV4_OFFSET			12
163*6cefaae1SJack Meng 
164*6cefaae1SJack Meng #define	IBFT_INVALID_MSG		"Invalid iBFT table 0x%x"
165*6cefaae1SJack Meng 
166*6cefaae1SJack Meng typedef enum ibft_status {
167*6cefaae1SJack Meng 	IBFT_STATUS_OK = 0,
168*6cefaae1SJack Meng 	/* General error */
169*6cefaae1SJack Meng 	IBFT_STATUS_ERR,
170*6cefaae1SJack Meng 	/* Bad header */
171*6cefaae1SJack Meng 	IBFT_STATUS_BADHDR,
172*6cefaae1SJack Meng 	/* Bad control ID */
173*6cefaae1SJack Meng 	IBFT_STATUS_BADCID,
174*6cefaae1SJack Meng 	/* Bad ip addr */
175*6cefaae1SJack Meng 	IBFT_STATUS_BADIP,
176*6cefaae1SJack Meng 	/* Bad af */
177*6cefaae1SJack Meng 	IBFT_STATUS_BADAF,
178*6cefaae1SJack Meng 	/* Bad chap name */
179*6cefaae1SJack Meng 	IBFT_STATUS_BADCHAPNAME,
180*6cefaae1SJack Meng 	/* Bad chap secret */
181*6cefaae1SJack Meng 	IBFT_STATUS_BADCHAPSEC,
182*6cefaae1SJack Meng 	/* Bad checksum */
183*6cefaae1SJack Meng 	IBFT_STATUS_BADCHECKSUM,
184*6cefaae1SJack Meng 	/* Low memory */
185*6cefaae1SJack Meng 	IBFT_STATUS_LOWMEM,
186*6cefaae1SJack Meng 	/* No table */
187*6cefaae1SJack Meng 	IBFT_STATUS_NOTABLE
188*6cefaae1SJack Meng } ibft_status_t;
189*6cefaae1SJack Meng 
190*6cefaae1SJack Meng extern void *memset(void *s, int c, size_t n);
191*6cefaae1SJack Meng extern int memcmp(const void *s1, const void *s2, size_t n);
192*6cefaae1SJack Meng extern void bcopy(const void *s1, void *s2, size_t n);
193*6cefaae1SJack Meng extern void iscsi_print_boot_property();
194*6cefaae1SJack Meng 
195*6cefaae1SJack Meng ib_boot_prop_t boot_property;		/* static allocated */
196*6cefaae1SJack Meng extern ib_boot_prop_t *iscsiboot_prop;	/* to be filled */
197*6cefaae1SJack Meng 
198*6cefaae1SJack Meng static ibft_status_t iscsi_parse_ibft_control(iscsi_ibft_ctl_t *ctl_hdr,
199*6cefaae1SJack Meng     ushort_t *iscsi_offset_buf);
200*6cefaae1SJack Meng 
201*6cefaae1SJack Meng static ibft_status_t iscsi_parse_ibft_initiator(char *begin_of_ibft,
202*6cefaae1SJack Meng     iscsi_ibft_initiator_t *initiator);
203*6cefaae1SJack Meng 
204*6cefaae1SJack Meng static ibft_status_t iscsi_parse_ibft_NIC(iscsi_ibft_nic_t *nicp);
205*6cefaae1SJack Meng 
206*6cefaae1SJack Meng static ibft_status_t iscsi_parse_ibft_target(char *begin_of_ibft,
207*6cefaae1SJack Meng     iscsi_ibft_tgt_t *tgtp);
208*6cefaae1SJack Meng 
209*6cefaae1SJack Meng 
210*6cefaae1SJack Meng /*
211*6cefaae1SJack Meng  * Return value:
212*6cefaae1SJack Meng  * Success: IBFT_STATUS_OK
213*6cefaae1SJack Meng  * Fail: IBFT_STATUS_BADCHECKSUM
214*6cefaae1SJack Meng  */
215*6cefaae1SJack Meng static ibft_status_t
216*6cefaae1SJack Meng iscsi_ibft_hdr_checksum(iscsi_ibft_tbl_hdr_t *tbl_hdr)
217*6cefaae1SJack Meng {
218*6cefaae1SJack Meng 	uchar_t	checksum    =	0;
219*6cefaae1SJack Meng 	uchar_t	*start	    =	NULL;
220*6cefaae1SJack Meng 	int	length	    =	0;
221*6cefaae1SJack Meng 	int	i	    =	0;
222*6cefaae1SJack Meng 
223*6cefaae1SJack Meng 	if (tbl_hdr == NULL) {
224*6cefaae1SJack Meng 		return (IBFT_STATUS_BADHDR);
225*6cefaae1SJack Meng 	}
226*6cefaae1SJack Meng 
227*6cefaae1SJack Meng 	length = tbl_hdr->Length;
228*6cefaae1SJack Meng 	start = (uchar_t *)tbl_hdr;
229*6cefaae1SJack Meng 
230*6cefaae1SJack Meng 	for (i = 0; i < length; i++) {
231*6cefaae1SJack Meng 		checksum = checksum + start[i];
232*6cefaae1SJack Meng 	}
233*6cefaae1SJack Meng 
234*6cefaae1SJack Meng 	if (!checksum)
235*6cefaae1SJack Meng 		return (IBFT_STATUS_OK);
236*6cefaae1SJack Meng 	else
237*6cefaae1SJack Meng 		return (IBFT_STATUS_BADCHECKSUM);
238*6cefaae1SJack Meng }
239*6cefaae1SJack Meng 
240*6cefaae1SJack Meng /*
241*6cefaae1SJack Meng  * Now we only support one control structure in the IBFT.
242*6cefaae1SJack Meng  * So there is no Control ID here.
243*6cefaae1SJack Meng  */
244*6cefaae1SJack Meng static ibft_status_t
245*6cefaae1SJack Meng iscsi_parse_ibft_structure(char *begin_of_ibft, char *buf)
246*6cefaae1SJack Meng {
247*6cefaae1SJack Meng 	iscsi_ibft_hdr_t	*hdr	=   NULL;
248*6cefaae1SJack Meng 	ibft_status_t		ret	=   IBFT_STATUS_OK;
249*6cefaae1SJack Meng 
250*6cefaae1SJack Meng 	if (buf == NULL) {
251*6cefaae1SJack Meng 		return (IBFT_STATUS_ERR);
252*6cefaae1SJack Meng 	}
253*6cefaae1SJack Meng 
254*6cefaae1SJack Meng 	hdr = (iscsi_ibft_hdr_t *)buf;
255*6cefaae1SJack Meng 	switch (hdr->Structure_id) {
256*6cefaae1SJack Meng 		case Initiator:
257*6cefaae1SJack Meng 			ret = iscsi_parse_ibft_initiator(
258*6cefaae1SJack Meng 			    begin_of_ibft,
259*6cefaae1SJack Meng 			    (iscsi_ibft_initiator_t *)buf);
260*6cefaae1SJack Meng 			break;
261*6cefaae1SJack Meng 		case Nic:
262*6cefaae1SJack Meng 			ret = iscsi_parse_ibft_NIC(
263*6cefaae1SJack Meng 			    (iscsi_ibft_nic_t *)buf);
264*6cefaae1SJack Meng 			break;
265*6cefaae1SJack Meng 		case Target:
266*6cefaae1SJack Meng 			ret = iscsi_parse_ibft_target(
267*6cefaae1SJack Meng 			    begin_of_ibft,
268*6cefaae1SJack Meng 			    (iscsi_ibft_tgt_t *)buf);
269*6cefaae1SJack Meng 			break;
270*6cefaae1SJack Meng 		default:
271*6cefaae1SJack Meng 			ret = IBFT_STATUS_BADHDR;
272*6cefaae1SJack Meng 			break;
273*6cefaae1SJack Meng 	}
274*6cefaae1SJack Meng 
275*6cefaae1SJack Meng 	return (ret);
276*6cefaae1SJack Meng }
277*6cefaae1SJack Meng 
278*6cefaae1SJack Meng /*
279*6cefaae1SJack Meng  * Parse the iBFT table
280*6cefaae1SJack Meng  * return IBFT_STATUS_OK upon sucess
281*6cefaae1SJack Meng  */
282*6cefaae1SJack Meng static ibft_status_t
283*6cefaae1SJack Meng iscsi_parse_ibft_tbl(iscsi_ibft_tbl_hdr_t *tbl_hdr)
284*6cefaae1SJack Meng {
285*6cefaae1SJack Meng 	char		*outbuf	    =	NULL;
286*6cefaae1SJack Meng 	int		i	    =	0;
287*6cefaae1SJack Meng 	ibft_status_t	ret	    =	IBFT_STATUS_OK;
288*6cefaae1SJack Meng 	ushort_t	iscsi_offset_buf[IBFT_OFFSET_BUF_LEN] = {0};
289*6cefaae1SJack Meng 
290*6cefaae1SJack Meng 	if (tbl_hdr == NULL) {
291*6cefaae1SJack Meng 		return (IBFT_STATUS_ERR);
292*6cefaae1SJack Meng 	}
293*6cefaae1SJack Meng 
294*6cefaae1SJack Meng 	if (iscsi_ibft_hdr_checksum(tbl_hdr) != IBFT_STATUS_OK) {
295*6cefaae1SJack Meng 		return (IBFT_STATUS_BADCHECKSUM);
296*6cefaae1SJack Meng 	}
297*6cefaae1SJack Meng 
298*6cefaae1SJack Meng 	outbuf = (char *)tbl_hdr;
299*6cefaae1SJack Meng 
300*6cefaae1SJack Meng 	ret = iscsi_parse_ibft_control(
301*6cefaae1SJack Meng 	    (iscsi_ibft_ctl_t *)&outbuf[ISCSI_IBFT_CTL_OFFSET],
302*6cefaae1SJack Meng 	    iscsi_offset_buf);
303*6cefaae1SJack Meng 
304*6cefaae1SJack Meng 	if (ret == IBFT_STATUS_OK) {
305*6cefaae1SJack Meng 		ret = IBFT_STATUS_ERR;
306*6cefaae1SJack Meng 		for (i = 0; i < IBFT_OFFSET_BUF_LEN; i++) {
307*6cefaae1SJack Meng 			if (iscsi_offset_buf[i] != 0) {
308*6cefaae1SJack Meng 				ret = iscsi_parse_ibft_structure(
309*6cefaae1SJack Meng 				    (char *)tbl_hdr,
310*6cefaae1SJack Meng 				    (char *)tbl_hdr +
311*6cefaae1SJack Meng 				    iscsi_offset_buf[i]);
312*6cefaae1SJack Meng 				if (ret != IBFT_STATUS_OK) {
313*6cefaae1SJack Meng 					return (ret);
314*6cefaae1SJack Meng 				}
315*6cefaae1SJack Meng 			}
316*6cefaae1SJack Meng 		}
317*6cefaae1SJack Meng 	}
318*6cefaae1SJack Meng 
319*6cefaae1SJack Meng 	return (ret);
320*6cefaae1SJack Meng }
321*6cefaae1SJack Meng 
322*6cefaae1SJack Meng static ibft_status_t
323*6cefaae1SJack Meng iscsi_parse_ibft_control(iscsi_ibft_ctl_t *ctl_hdr,
324*6cefaae1SJack Meng     ushort_t	*iscsi_offset_buf)
325*6cefaae1SJack Meng {
326*6cefaae1SJack Meng 	int	    i		=	0;
327*6cefaae1SJack Meng 	ushort_t    *offsetp	=	NULL;
328*6cefaae1SJack Meng 
329*6cefaae1SJack Meng 	if (ctl_hdr == NULL) {
330*6cefaae1SJack Meng 		return (IBFT_STATUS_BADHDR);
331*6cefaae1SJack Meng 	}
332*6cefaae1SJack Meng 
333*6cefaae1SJack Meng 	if (ctl_hdr->header.Structure_id != Control) {
334*6cefaae1SJack Meng 		return (IBFT_STATUS_BADCID);
335*6cefaae1SJack Meng 	}
336*6cefaae1SJack Meng 
337*6cefaae1SJack Meng 	/*
338*6cefaae1SJack Meng 	 * Copy the offsets to offset buffer.
339*6cefaae1SJack Meng 	 */
340*6cefaae1SJack Meng 	for (offsetp = &(ctl_hdr->Initiator_offset); i < IBFT_OFFSET_BUF_LEN;
341*6cefaae1SJack Meng 	    offsetp++) {
342*6cefaae1SJack Meng 		iscsi_offset_buf[i++] = *offsetp;
343*6cefaae1SJack Meng 	}
344*6cefaae1SJack Meng 
345*6cefaae1SJack Meng 	return (IBFT_STATUS_OK);
346*6cefaae1SJack Meng }
347*6cefaae1SJack Meng 
348*6cefaae1SJack Meng /*
349*6cefaae1SJack Meng  * We only copy the "Firmare Boot Selseted" and valid initiator
350*6cefaae1SJack Meng  * to the boot property.
351*6cefaae1SJack Meng  */
352*6cefaae1SJack Meng static ibft_status_t
353*6cefaae1SJack Meng iscsi_parse_ibft_initiator(char *begin_of_ibft,
354*6cefaae1SJack Meng     iscsi_ibft_initiator_t *initiator)
355*6cefaae1SJack Meng {
356*6cefaae1SJack Meng 	if (initiator == NULL) {
357*6cefaae1SJack Meng 		return (IBFT_STATUS_ERR);
358*6cefaae1SJack Meng 	}
359*6cefaae1SJack Meng 
360*6cefaae1SJack Meng 	if (initiator->header.Structure_id != Initiator) {
361*6cefaae1SJack Meng 		return (IBFT_STATUS_BADHDR);
362*6cefaae1SJack Meng 	}
363*6cefaae1SJack Meng 
364*6cefaae1SJack Meng 	if ((initiator->header.Flags & IBFT_FIRMWARE_BOOT_SELECTED) &&
365*6cefaae1SJack Meng 	    (initiator->header.Flags & IBFT_BLOCK_VALID_YES)) {
366*6cefaae1SJack Meng 		/*
367*6cefaae1SJack Meng 		 * If the initiator name exists, we will copy it to our own
368*6cefaae1SJack Meng 		 * property structure
369*6cefaae1SJack Meng 		 */
370*6cefaae1SJack Meng 		if (initiator->ini_name_len != 0) {
371*6cefaae1SJack Meng 			boot_property.boot_init.ini_name =
372*6cefaae1SJack Meng 			    (uchar_t *)kmem_zalloc(
373*6cefaae1SJack Meng 			    initiator->ini_name_len + 1, KM_SLEEP);
374*6cefaae1SJack Meng 			(void) snprintf(
375*6cefaae1SJack Meng 			    (char *)boot_property.boot_init.ini_name,
376*6cefaae1SJack Meng 			    initiator->ini_name_len + 1, "%s",
377*6cefaae1SJack Meng 			    begin_of_ibft + initiator->ini_name_offset);
378*6cefaae1SJack Meng 		}
379*6cefaae1SJack Meng 	}
380*6cefaae1SJack Meng 	return (IBFT_STATUS_OK);
381*6cefaae1SJack Meng }
382*6cefaae1SJack Meng 
383*6cefaae1SJack Meng static ibft_status_t
384*6cefaae1SJack Meng iscsi_parse_ipaddr(uchar_t *source, char *dest, int *af)
385*6cefaae1SJack Meng {
386*6cefaae1SJack Meng 	int i = 0;
387*6cefaae1SJack Meng 
388*6cefaae1SJack Meng 	if (source == NULL) {
389*6cefaae1SJack Meng 		return (IBFT_STATUS_ERR);
390*6cefaae1SJack Meng 	}
391*6cefaae1SJack Meng 
392*6cefaae1SJack Meng 	if (source[0] == 0x00 && source[1] == 0x00 &&
393*6cefaae1SJack Meng 	    source[2] == 0x00 && source[3] == 0x00 &&
394*6cefaae1SJack Meng 	    source[4] == 0x00 && source[5] == 0x00 &&
395*6cefaae1SJack Meng 	    source[6] == 0x00 && source[7] == 0x00 &&
396*6cefaae1SJack Meng 	    source[8] == 0x00 && source[9] == 0x00 &&
397*6cefaae1SJack Meng 	    (source[10] == 0xff) && (source[11] == 0xff)) {
398*6cefaae1SJack Meng 		/*
399*6cefaae1SJack Meng 		 * IPv4 address
400*6cefaae1SJack Meng 		 */
401*6cefaae1SJack Meng 		if (dest != NULL) {
402*6cefaae1SJack Meng 			(void) sprintf(dest, "%d.%d.%d.%d",
403*6cefaae1SJack Meng 			    source[12], source[13], source[14], source[15]);
404*6cefaae1SJack Meng 		}
405*6cefaae1SJack Meng 		if (af != NULL) {
406*6cefaae1SJack Meng 			*af = AF_INET;
407*6cefaae1SJack Meng 		}
408*6cefaae1SJack Meng 	} else {
409*6cefaae1SJack Meng 		if (dest != NULL) {
410*6cefaae1SJack Meng 			for (i = 0; i < 14; i = i + 2) {
411*6cefaae1SJack Meng 				(void) sprintf(dest, "%02x%02x:", source[i],
412*6cefaae1SJack Meng 				    source[i+1]);
413*6cefaae1SJack Meng 				dest = dest + 5;
414*6cefaae1SJack Meng 			}
415*6cefaae1SJack Meng 			(void) sprintf(dest, "%02x%02x",
416*6cefaae1SJack Meng 			    source[i], source[i+1]);
417*6cefaae1SJack Meng 		}
418*6cefaae1SJack Meng 		if (af != NULL) {
419*6cefaae1SJack Meng 			*af = AF_INET6;
420*6cefaae1SJack Meng 		}
421*6cefaae1SJack Meng 	}
422*6cefaae1SJack Meng 
423*6cefaae1SJack Meng 	return (IBFT_STATUS_OK);
424*6cefaae1SJack Meng }
425*6cefaae1SJack Meng 
426*6cefaae1SJack Meng /*
427*6cefaae1SJack Meng  * Copy the ip address from ibft. If IPv4 is used, we should copy
428*6cefaae1SJack Meng  * the address from 12th byte.
429*6cefaae1SJack Meng  */
430*6cefaae1SJack Meng static ibft_status_t
431*6cefaae1SJack Meng iscsi_copy_ibft_ipaddr(uchar_t *source, void *dest, int *af)
432*6cefaae1SJack Meng {
433*6cefaae1SJack Meng 	ibft_status_t	ret		=	IBFT_STATUS_OK;
434*6cefaae1SJack Meng 	int		sin_family	=	0;
435*6cefaae1SJack Meng 
436*6cefaae1SJack Meng 	if (source == NULL || dest == NULL) {
437*6cefaae1SJack Meng 		return (IBFT_STATUS_ERR);
438*6cefaae1SJack Meng 	}
439*6cefaae1SJack Meng 	ret = iscsi_parse_ipaddr(source, NULL, &sin_family);
440*6cefaae1SJack Meng 	if (ret != 0) {
441*6cefaae1SJack Meng 		return (IBFT_STATUS_BADIP);
442*6cefaae1SJack Meng 	}
443*6cefaae1SJack Meng 
444*6cefaae1SJack Meng 	if (sin_family == AF_INET) {
445*6cefaae1SJack Meng 		bcopy(source+IPV4_OFFSET, dest, sizeof (struct in_addr));
446*6cefaae1SJack Meng 	} else if (sin_family == AF_INET6) {
447*6cefaae1SJack Meng 		bcopy(source, dest, sizeof (struct in6_addr));
448*6cefaae1SJack Meng 	} else {
449*6cefaae1SJack Meng 		return (IBFT_STATUS_BADAF);
450*6cefaae1SJack Meng 	}
451*6cefaae1SJack Meng 
452*6cefaae1SJack Meng 	if (af != NULL) {
453*6cefaae1SJack Meng 		*af = sin_family;
454*6cefaae1SJack Meng 	}
455*6cefaae1SJack Meng 	return (IBFT_STATUS_OK);
456*6cefaae1SJack Meng }
457*6cefaae1SJack Meng 
458*6cefaae1SJack Meng /*
459*6cefaae1SJack Meng  * Maybe there are multiply NICs are available. We only copy the
460*6cefaae1SJack Meng  * "Firmare Boot Selseted" and valid one to the boot property.
461*6cefaae1SJack Meng  */
462*6cefaae1SJack Meng static ibft_status_t
463*6cefaae1SJack Meng iscsi_parse_ibft_NIC(iscsi_ibft_nic_t *nicp)
464*6cefaae1SJack Meng {
465*6cefaae1SJack Meng 	ibft_status_t	ret	=	IBFT_STATUS_OK;
466*6cefaae1SJack Meng 	int		af	=	0;
467*6cefaae1SJack Meng 
468*6cefaae1SJack Meng 	if (nicp == NULL) {
469*6cefaae1SJack Meng 		return (IBFT_STATUS_ERR);
470*6cefaae1SJack Meng 	}
471*6cefaae1SJack Meng 
472*6cefaae1SJack Meng 	if (nicp->header.Structure_id != Nic) {
473*6cefaae1SJack Meng 		return (IBFT_STATUS_ERR);
474*6cefaae1SJack Meng 	}
475*6cefaae1SJack Meng 
476*6cefaae1SJack Meng 	if ((nicp->header.Flags & IBFT_FIRMWARE_BOOT_SELECTED) &&
477*6cefaae1SJack Meng 	    (nicp->header.Flags & IBFT_BLOCK_VALID_YES)) {
478*6cefaae1SJack Meng 		ret = iscsi_copy_ibft_ipaddr(nicp->ip_addr,
479*6cefaae1SJack Meng 		    &boot_property.boot_nic.nic_ip_u, &af);
480*6cefaae1SJack Meng 		if (ret != IBFT_STATUS_OK) {
481*6cefaae1SJack Meng 			return (ret);
482*6cefaae1SJack Meng 		}
483*6cefaae1SJack Meng 
484*6cefaae1SJack Meng 		boot_property.boot_nic.sin_family = af;
485*6cefaae1SJack Meng 
486*6cefaae1SJack Meng 		ret = iscsi_copy_ibft_ipaddr(nicp->Gateway,
487*6cefaae1SJack Meng 		    &boot_property.boot_nic.nic_gw_u, NULL);
488*6cefaae1SJack Meng 		if (ret != IBFT_STATUS_OK) {
489*6cefaae1SJack Meng 			return (ret);
490*6cefaae1SJack Meng 		}
491*6cefaae1SJack Meng 
492*6cefaae1SJack Meng 		ret = iscsi_copy_ibft_ipaddr(nicp->dhcp,
493*6cefaae1SJack Meng 		    &boot_property.boot_nic.nic_dhcp_u, NULL);
494*6cefaae1SJack Meng 		if (ret != IBFT_STATUS_OK) {
495*6cefaae1SJack Meng 			return (ret);
496*6cefaae1SJack Meng 		}
497*6cefaae1SJack Meng 
498*6cefaae1SJack Meng 		bcopy(nicp->mac, boot_property.boot_nic.nic_mac, 6);
499*6cefaae1SJack Meng 		boot_property.boot_nic.sub_mask_prefix =
500*6cefaae1SJack Meng 		    nicp->Subnet_Mask_Prefix;
501*6cefaae1SJack Meng 	}
502*6cefaae1SJack Meng 
503*6cefaae1SJack Meng 	return (IBFT_STATUS_OK);
504*6cefaae1SJack Meng }
505*6cefaae1SJack Meng 
506*6cefaae1SJack Meng /*
507*6cefaae1SJack Meng  * Maybe there are multiply targets are available. We only copy the
508*6cefaae1SJack Meng  * "Firmare Boot Selseted" and valid one to the boot property.
509*6cefaae1SJack Meng  */
510*6cefaae1SJack Meng static ibft_status_t
511*6cefaae1SJack Meng iscsi_parse_ibft_target(char *begin_of_ibft, iscsi_ibft_tgt_t *tgtp)
512*6cefaae1SJack Meng {
513*6cefaae1SJack Meng 	char		*tmp	=   NULL;
514*6cefaae1SJack Meng 	int		af	=   0;
515*6cefaae1SJack Meng 	ibft_status_t	ret	=   IBFT_STATUS_OK;
516*6cefaae1SJack Meng 
517*6cefaae1SJack Meng 	if (tgtp == NULL) {
518*6cefaae1SJack Meng 		return (IBFT_STATUS_ERR);
519*6cefaae1SJack Meng 	}
520*6cefaae1SJack Meng 
521*6cefaae1SJack Meng 	if (tgtp->header.Structure_id != Target) {
522*6cefaae1SJack Meng 		return (IBFT_STATUS_BADHDR);
523*6cefaae1SJack Meng 	}
524*6cefaae1SJack Meng 
525*6cefaae1SJack Meng 	if ((tgtp->header.Flags & IBFT_FIRMWARE_BOOT_SELECTED) &&
526*6cefaae1SJack Meng 	    (tgtp->header.Flags & IBFT_BLOCK_VALID_YES)) {
527*6cefaae1SJack Meng 		/*
528*6cefaae1SJack Meng 		 * Get Target Address
529*6cefaae1SJack Meng 		 */
530*6cefaae1SJack Meng 		ret = iscsi_copy_ibft_ipaddr(tgtp->ip_addr,
531*6cefaae1SJack Meng 		    &boot_property.boot_tgt.tgt_ip_u, &af);
532*6cefaae1SJack Meng 		if (ret != IBFT_STATUS_OK) {
533*6cefaae1SJack Meng 			return (ret);
534*6cefaae1SJack Meng 		}
535*6cefaae1SJack Meng 		boot_property.boot_tgt.sin_family = af;
536*6cefaae1SJack Meng 		/*
537*6cefaae1SJack Meng 		 * Get Target Name
538*6cefaae1SJack Meng 		 */
539*6cefaae1SJack Meng 		if (tgtp->target_name_len != 0) {
540*6cefaae1SJack Meng 			boot_property.boot_tgt.tgt_name =
541*6cefaae1SJack Meng 			    (uchar_t *)kmem_zalloc(tgtp->target_name_len + 1,
542*6cefaae1SJack Meng 			    KM_SLEEP);
543*6cefaae1SJack Meng 			(void) snprintf(
544*6cefaae1SJack Meng 			    (char *)boot_property.boot_tgt.tgt_name,
545*6cefaae1SJack Meng 			    tgtp->target_name_len + 1, "%s",
546*6cefaae1SJack Meng 			    begin_of_ibft + tgtp->target_name_offset);
547*6cefaae1SJack Meng 		} else {
548*6cefaae1SJack Meng 			boot_property.boot_tgt.tgt_name = NULL;
549*6cefaae1SJack Meng 		}
550*6cefaae1SJack Meng 
551*6cefaae1SJack Meng 		/* Get Dest Port */
552*6cefaae1SJack Meng 		boot_property.boot_tgt.tgt_port = tgtp->port;
553*6cefaae1SJack Meng 
554*6cefaae1SJack Meng 		boot_property.boot_tgt.lun_online = 0;
555*6cefaae1SJack Meng 
556*6cefaae1SJack Meng 		/*
557*6cefaae1SJack Meng 		 * Get CHAP secret and name.
558*6cefaae1SJack Meng 		 */
559*6cefaae1SJack Meng 		if (tgtp->chap_type != NO_CHAP) {
560*6cefaae1SJack Meng 			if (tgtp->chap_name_len != 0) {
561*6cefaae1SJack Meng 				boot_property.boot_init.ini_chap_name =
562*6cefaae1SJack Meng 				    (uchar_t *)kmem_zalloc(
563*6cefaae1SJack Meng 				    tgtp->chap_name_len + 1,
564*6cefaae1SJack Meng 				    KM_SLEEP);
565*6cefaae1SJack Meng 				tmp = (char *)
566*6cefaae1SJack Meng 				    boot_property.boot_init.ini_chap_name;
567*6cefaae1SJack Meng 				(void) snprintf(
568*6cefaae1SJack Meng 				    tmp,
569*6cefaae1SJack Meng 				    tgtp->chap_name_len + 1, "%s",
570*6cefaae1SJack Meng 				    begin_of_ibft + tgtp->chap_name_offset);
571*6cefaae1SJack Meng 			} else {
572*6cefaae1SJack Meng 				/*
573*6cefaae1SJack Meng 				 * Just set NULL, initiator is able to deal
574*6cefaae1SJack Meng 				 * with this
575*6cefaae1SJack Meng 				 */
576*6cefaae1SJack Meng 				boot_property.boot_init.ini_chap_name = NULL;
577*6cefaae1SJack Meng 			}
578*6cefaae1SJack Meng 
579*6cefaae1SJack Meng 			if (tgtp->chap_secret_len != 0) {
580*6cefaae1SJack Meng 				boot_property.boot_init.ini_chap_sec =
581*6cefaae1SJack Meng 				    (uchar_t *)kmem_zalloc(
582*6cefaae1SJack Meng 				    tgtp->chap_secret_len + 1,
583*6cefaae1SJack Meng 				    KM_SLEEP);
584*6cefaae1SJack Meng 				bcopy(begin_of_ibft +
585*6cefaae1SJack Meng 				    tgtp->chap_secret_offset,
586*6cefaae1SJack Meng 				    boot_property.boot_init.ini_chap_sec,
587*6cefaae1SJack Meng 				    tgtp->chap_secret_len);
588*6cefaae1SJack Meng 			} else {
589*6cefaae1SJack Meng 				boot_property.boot_init.ini_chap_sec = NULL;
590*6cefaae1SJack Meng 				return (IBFT_STATUS_ERR);
591*6cefaae1SJack Meng 			}
592*6cefaae1SJack Meng 
593*6cefaae1SJack Meng 			if (tgtp->chap_type == Mutual_CHAP) {
594*6cefaae1SJack Meng 				if (tgtp->rev_chap_name_len != 0) {
595*6cefaae1SJack Meng 					boot_property.boot_tgt.tgt_chap_name =
596*6cefaae1SJack Meng 					    (uchar_t *)kmem_zalloc(
597*6cefaae1SJack Meng 					    tgtp->chap_name_len + 1,
598*6cefaae1SJack Meng 					    KM_SLEEP);
599*6cefaae1SJack Meng #define	TGT_CHAP_NAME	boot_property.boot_tgt.tgt_chap_name
600*6cefaae1SJack Meng 					tmp = (char *)TGT_CHAP_NAME;
601*6cefaae1SJack Meng #undef	TGT_CHAP_NAME
602*6cefaae1SJack Meng 					(void) snprintf(
603*6cefaae1SJack Meng 					    tmp,
604*6cefaae1SJack Meng 					    tgtp->chap_name_len + 1,
605*6cefaae1SJack Meng 					    "%s",
606*6cefaae1SJack Meng 					    begin_of_ibft +
607*6cefaae1SJack Meng 					    tgtp->rev_chap_name_offset);
608*6cefaae1SJack Meng 				} else {
609*6cefaae1SJack Meng 					/*
610*6cefaae1SJack Meng 					 * Just set NULL, initiator is able
611*6cefaae1SJack Meng 					 * to deal with this
612*6cefaae1SJack Meng 					 */
613*6cefaae1SJack Meng 					boot_property.boot_tgt.tgt_chap_name =
614*6cefaae1SJack Meng 					    NULL;
615*6cefaae1SJack Meng 				}
616*6cefaae1SJack Meng 
617*6cefaae1SJack Meng 				if (tgtp->rev_chap_secret_len != 0) {
618*6cefaae1SJack Meng 					boot_property.boot_tgt.tgt_chap_sec =
619*6cefaae1SJack Meng 					    (uchar_t *)kmem_zalloc(
620*6cefaae1SJack Meng 					    tgtp->rev_chap_secret_len + 1,
621*6cefaae1SJack Meng 					    KM_SLEEP);
622*6cefaae1SJack Meng 					tmp = (char *)
623*6cefaae1SJack Meng 					    boot_property.boot_tgt.tgt_chap_sec;
624*6cefaae1SJack Meng 					(void) snprintf(
625*6cefaae1SJack Meng 					    tmp,
626*6cefaae1SJack Meng 					    tgtp->rev_chap_secret_len + 1,
627*6cefaae1SJack Meng 					    "%s",
628*6cefaae1SJack Meng 					    begin_of_ibft +
629*6cefaae1SJack Meng 					    tgtp->chap_secret_offset);
630*6cefaae1SJack Meng 				} else {
631*6cefaae1SJack Meng 					boot_property.boot_tgt.tgt_chap_sec =
632*6cefaae1SJack Meng 					    NULL;
633*6cefaae1SJack Meng 					return (IBFT_STATUS_BADCHAPSEC);
634*6cefaae1SJack Meng 				}
635*6cefaae1SJack Meng 			}
636*6cefaae1SJack Meng 		} else {
637*6cefaae1SJack Meng 			boot_property.boot_init.ini_chap_name = NULL;
638*6cefaae1SJack Meng 			boot_property.boot_init.ini_chap_sec = NULL;
639*6cefaae1SJack Meng 		}
640*6cefaae1SJack Meng 
641*6cefaae1SJack Meng 		/*
642*6cefaae1SJack Meng 		 * Get Boot LUN
643*6cefaae1SJack Meng 		 */
644*6cefaae1SJack Meng 		(void) bcopy(tgtp->boot_lun,
645*6cefaae1SJack Meng 		    boot_property.boot_tgt.tgt_boot_lun, 8);
646*6cefaae1SJack Meng 	}
647*6cefaae1SJack Meng 
648*6cefaae1SJack Meng 	return (IBFT_STATUS_OK);
649*6cefaae1SJack Meng }
650*6cefaae1SJack Meng 
651*6cefaae1SJack Meng /*
652*6cefaae1SJack Meng  * This function is used for scanning iBFT from the physical memory.
653*6cefaae1SJack Meng  * Return Value:
654*6cefaae1SJack Meng  * IBFT_STATUS_OK
655*6cefaae1SJack Meng  * IBFT_STATUS_ERR
656*6cefaae1SJack Meng  */
657*6cefaae1SJack Meng static ibft_status_t
658*6cefaae1SJack Meng iscsi_scan_ibft_tbl(char *ibft_tbl_buf)
659*6cefaae1SJack Meng {
660*6cefaae1SJack Meng 	int		start;
661*6cefaae1SJack Meng 	void		*va		= NULL;
662*6cefaae1SJack Meng 	int		*len 		= NULL;
663*6cefaae1SJack Meng 	ibft_status_t	ret		= IBFT_STATUS_NOTABLE;
664*6cefaae1SJack Meng 
665*6cefaae1SJack Meng 	for (start = ISCSI_IBFT_LOWER_ADDR; start < ISCSI_IBFT_HIGHER_ADDR;
666*6cefaae1SJack Meng 	    start = start + ISCSI_IBFT_ALIGNED) {
667*6cefaae1SJack Meng 		va = (void *)psm_map((paddr_t)(start&0xffffffff),
668*6cefaae1SJack Meng 		    ISCSI_IBFT_SIGNATURE_LEN,
669*6cefaae1SJack Meng 		    PROT_READ);
670*6cefaae1SJack Meng 
671*6cefaae1SJack Meng 		if (va == NULL) {
672*6cefaae1SJack Meng 			continue;
673*6cefaae1SJack Meng 		}
674*6cefaae1SJack Meng 		if (memcmp(va, ISCSI_IBFT_SIGNATRUE,
675*6cefaae1SJack Meng 		    ISCSI_IBFT_SIGNATURE_LEN) == 0) {
676*6cefaae1SJack Meng 			ret = IBFT_STATUS_ERR;
677*6cefaae1SJack Meng 			/* Acquire table length */
678*6cefaae1SJack Meng 			len = (int *)psm_map(
679*6cefaae1SJack Meng 			    (paddr_t)((start+\
680*6cefaae1SJack Meng 			    ISCSI_IBFT_SIGNATURE_LEN)&0xffffffff),
681*6cefaae1SJack Meng 			    ISCSI_IBFT_SIGNATURE_LEN, PROT_READ);
682*6cefaae1SJack Meng 			if (len == NULL) {
683*6cefaae1SJack Meng 				psm_unmap((caddr_t)va,
684*6cefaae1SJack Meng 				    ISCSI_IBFT_SIGNATURE_LEN);
685*6cefaae1SJack Meng 				continue;
686*6cefaae1SJack Meng 			}
687*6cefaae1SJack Meng 			if (ISCSI_IBFT_LOWER_ADDR + *len <
688*6cefaae1SJack Meng 			    ISCSI_IBFT_HIGHER_ADDR - 1) {
689*6cefaae1SJack Meng 				psm_unmap(va,
690*6cefaae1SJack Meng 				    ISCSI_IBFT_SIGNATURE_LEN);
691*6cefaae1SJack Meng 				va = psm_map((paddr_t)(start&0xffffffff),
692*6cefaae1SJack Meng 				    *len,
693*6cefaae1SJack Meng 				    PROT_READ);
694*6cefaae1SJack Meng 				if (va != NULL) {
695*6cefaae1SJack Meng 					/*
696*6cefaae1SJack Meng 					 * Copy data to our own buffer
697*6cefaae1SJack Meng 					 */
698*6cefaae1SJack Meng 					bcopy(va, ibft_tbl_buf, *len);
699*6cefaae1SJack Meng 					ret = IBFT_STATUS_OK;
700*6cefaae1SJack Meng 				}
701*6cefaae1SJack Meng 				psm_unmap((caddr_t)va, *len);
702*6cefaae1SJack Meng 				psm_unmap((caddr_t)len,
703*6cefaae1SJack Meng 				    ISCSI_IBFT_SIGNATURE_LEN);
704*6cefaae1SJack Meng 				break;
705*6cefaae1SJack Meng 			} else {
706*6cefaae1SJack Meng 				psm_unmap((caddr_t)va,
707*6cefaae1SJack Meng 				    ISCSI_IBFT_SIGNATURE_LEN);
708*6cefaae1SJack Meng 				psm_unmap((caddr_t)len,
709*6cefaae1SJack Meng 				    ISCSI_IBFT_SIGNATURE_LEN);
710*6cefaae1SJack Meng 			}
711*6cefaae1SJack Meng 		} else {
712*6cefaae1SJack Meng 			psm_unmap((caddr_t)va, ISCSI_IBFT_SIGNATURE_LEN);
713*6cefaae1SJack Meng 		}
714*6cefaae1SJack Meng 	}
715*6cefaae1SJack Meng 
716*6cefaae1SJack Meng 	return (ret);
717*6cefaae1SJack Meng }
718*6cefaae1SJack Meng 
719*6cefaae1SJack Meng /*
720*6cefaae1SJack Meng  * Scan the ibft table and store the iSCSI boot properties
721*6cefaae1SJack Meng  * If there is a valid table then set the iscsiboot_prop
722*6cefaae1SJack Meng  * iBF should be off if the host is not intended
723*6cefaae1SJack Meng  * to be booted from iSCSI disk
724*6cefaae1SJack Meng  */
725*6cefaae1SJack Meng void
726*6cefaae1SJack Meng ld_ib_prop()
727*6cefaae1SJack Meng {
728*6cefaae1SJack Meng 	ibft_status_t	ret	=   IBFT_STATUS_OK;
729*6cefaae1SJack Meng 	char		*ibft_tbl_buf;
730*6cefaae1SJack Meng 
731*6cefaae1SJack Meng 	ibft_tbl_buf = (char *)kmem_zalloc(ISCSI_IBFT_TBL_BUF_LEN,
732*6cefaae1SJack Meng 	    KM_SLEEP);
733*6cefaae1SJack Meng 
734*6cefaae1SJack Meng 	if (!ibft_tbl_buf) {
735*6cefaae1SJack Meng 		/* Unlikely to happen */
736*6cefaae1SJack Meng 		cmn_err(CE_NOTE, IBFT_INVALID_MSG,
737*6cefaae1SJack Meng 		    IBFT_STATUS_LOWMEM);
738*6cefaae1SJack Meng 		return;
739*6cefaae1SJack Meng 	}
740*6cefaae1SJack Meng 
741*6cefaae1SJack Meng 	(void) memset(&boot_property, 0, sizeof (boot_property));
742*6cefaae1SJack Meng 	if ((ret = iscsi_scan_ibft_tbl(ibft_tbl_buf)) ==
743*6cefaae1SJack Meng 	    IBFT_STATUS_OK) {
744*6cefaae1SJack Meng 		ret = iscsi_parse_ibft_tbl(
745*6cefaae1SJack Meng 		    (iscsi_ibft_tbl_hdr_t *)ibft_tbl_buf);
746*6cefaae1SJack Meng 		if (ret == IBFT_STATUS_OK) {
747*6cefaae1SJack Meng 			iscsiboot_prop = &boot_property;
748*6cefaae1SJack Meng 			iscsi_print_boot_property();
749*6cefaae1SJack Meng 		} else {
750*6cefaae1SJack Meng 			cmn_err(CE_NOTE, IBFT_INVALID_MSG, ret);
751*6cefaae1SJack Meng 		}
752*6cefaae1SJack Meng 	} else if (ret != IBFT_STATUS_NOTABLE) {
753*6cefaae1SJack Meng 		cmn_err(CE_NOTE, IBFT_INVALID_MSG, ret);
754*6cefaae1SJack Meng 	}
755*6cefaae1SJack Meng 
756*6cefaae1SJack Meng 	kmem_free(ibft_tbl_buf, ISCSI_IBFT_TBL_BUF_LEN);
757*6cefaae1SJack Meng }
758