xref: /titanic_41/usr/src/uts/i86pc/os/ibft.c (revision dedec472759b1a1a25044d504201ef59ccbffb56)
16cefaae1SJack Meng /*
26cefaae1SJack Meng  * CDDL HEADER START
36cefaae1SJack Meng  *
46cefaae1SJack Meng  * The contents of this file are subject to the terms of the
56cefaae1SJack Meng  * Common Development and Distribution License (the "License").
66cefaae1SJack Meng  * You may not use this file except in compliance with the License.
76cefaae1SJack Meng  *
86cefaae1SJack Meng  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
96cefaae1SJack Meng  * or http://www.opensolaris.org/os/licensing.
106cefaae1SJack Meng  * See the License for the specific language governing permissions
116cefaae1SJack Meng  * and limitations under the License.
126cefaae1SJack Meng  *
136cefaae1SJack Meng  * When distributing Covered Code, include this CDDL HEADER in each
146cefaae1SJack Meng  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
156cefaae1SJack Meng  * If applicable, add the following below this CDDL HEADER, with the
166cefaae1SJack Meng  * fields enclosed by brackets "[]" replaced with your own identifying
176cefaae1SJack Meng  * information: Portions Copyright [yyyy] [name of copyright owner]
186cefaae1SJack Meng  *
196cefaae1SJack Meng  * CDDL HEADER END
206cefaae1SJack Meng  */
216cefaae1SJack Meng 
226cefaae1SJack Meng /*
23474eb465Svitezslav batrla - Sun Microsystems - Prague Czech Republic  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
246cefaae1SJack Meng  * Use is subject to license terms.
256cefaae1SJack Meng  */
266cefaae1SJack Meng 
276cefaae1SJack Meng /*
286cefaae1SJack Meng  * This is the place to implement ld_ib_props()
296cefaae1SJack Meng  * For x86 it is to load iBFT and costruct the global ib props
306cefaae1SJack Meng  */
316cefaae1SJack Meng 
326cefaae1SJack Meng #include <sys/types.h>
336cefaae1SJack Meng #include <sys/cmn_err.h>
346cefaae1SJack Meng #include <sys/socket.h>
356cefaae1SJack Meng #include <netinet/in.h>
366cefaae1SJack Meng #include <sys/mman.h>
376cefaae1SJack Meng #include <sys/bootprops.h>
386cefaae1SJack Meng #include <sys/kmem.h>
396cefaae1SJack Meng #include <sys/psm.h>
40474eb465Svitezslav batrla - Sun Microsystems - Prague Czech Republic #include <sys/bootconf.h>
416cefaae1SJack Meng 
426cefaae1SJack Meng #ifndef	NULL
436cefaae1SJack Meng #define	NULL	0
446cefaae1SJack Meng #endif
456cefaae1SJack Meng 
466cefaae1SJack Meng typedef enum ibft_structure_type {
476cefaae1SJack Meng 	Reserved	=	0,
486cefaae1SJack Meng 	Control		=	1,
496cefaae1SJack Meng 	Initiator	=	2,
506cefaae1SJack Meng 	Nic		=	3,
516cefaae1SJack Meng 	Target		=	4,
526cefaae1SJack Meng 	Extensions	=	5,
536cefaae1SJack Meng 	Type_End
546cefaae1SJack Meng }ibft_struct_type;
556cefaae1SJack Meng 
566cefaae1SJack Meng typedef enum _chap_type {
576cefaae1SJack Meng 	NO_CHAP		=	0,
586cefaae1SJack Meng 	CHAP		=	1,
596cefaae1SJack Meng 	Mutual_CHAP	=	2,
606cefaae1SJack Meng 	TYPE_UNKNOWN
616cefaae1SJack Meng }chap_type;
626cefaae1SJack Meng 
636cefaae1SJack Meng typedef struct ibft_entry {
646cefaae1SJack Meng 	int	af;
656cefaae1SJack Meng 	int	e_port;
666cefaae1SJack Meng 	char	target_name[224];
676cefaae1SJack Meng 	char	target_addr[INET6_ADDRSTRLEN];
686cefaae1SJack Meng }ibft_entry_t;
696cefaae1SJack Meng 
706cefaae1SJack Meng typedef struct iSCSI_ibft_tbl_hdr {
716cefaae1SJack Meng 	char	    Signature[4];
726cefaae1SJack Meng 	int	    Length;
736cefaae1SJack Meng 	char	    Revision;
746cefaae1SJack Meng 	char	    Checksum;
756cefaae1SJack Meng 	char	    oem_id[6];
766cefaae1SJack Meng 	char	    oem_table_id[8];
776cefaae1SJack Meng 	char	    Reserved[24];
786cefaae1SJack Meng }iscsi_ibft_tbl_hdr_t;
796cefaae1SJack Meng 
806cefaae1SJack Meng typedef struct iSCSI_ibft_hdr {
816cefaae1SJack Meng 	char	    Structure_id;
826cefaae1SJack Meng 	char	    Version;
836cefaae1SJack Meng 	ushort_t    Length;
846cefaae1SJack Meng 	char	    Index;
856cefaae1SJack Meng 	char	    Flags;
866cefaae1SJack Meng }iscsi_ibft_hdr_t;
876cefaae1SJack Meng 
886cefaae1SJack Meng typedef struct iSCSI_ibft_control {
896cefaae1SJack Meng 	iscsi_ibft_hdr_t    header;
906cefaae1SJack Meng 	ushort_t	    Extensions;
916cefaae1SJack Meng 	ushort_t	    Initiator_offset;
926cefaae1SJack Meng 	ushort_t	    Nic0_offset;
936cefaae1SJack Meng 	ushort_t	    Target0_offset;
946cefaae1SJack Meng 	ushort_t	    Nic1_offset;
956cefaae1SJack Meng 	ushort_t	    Target1_offset;
966cefaae1SJack Meng }iscsi_ibft_ctl_t;
976cefaae1SJack Meng 
986cefaae1SJack Meng typedef struct iSCSI_ibft_initiator {
996cefaae1SJack Meng 	iscsi_ibft_hdr_t    header;
1006cefaae1SJack Meng 	uchar_t		    iSNS_Server[16];
1016cefaae1SJack Meng 	uchar_t		    SLP_Server[16];
1026cefaae1SJack Meng 	uchar_t		    Pri_Radius_Server[16];
1036cefaae1SJack Meng 	uchar_t		    Sec_Radius_Server[16];
1046cefaae1SJack Meng 	ushort_t	    ini_name_len;
1056cefaae1SJack Meng 	ushort_t	    ini_name_offset;
1066cefaae1SJack Meng }iscsi_ibft_initiator_t;
1076cefaae1SJack Meng 
1086cefaae1SJack Meng typedef struct iSCSI_ibft_nic {
1096cefaae1SJack Meng 	iscsi_ibft_hdr_t    header;
1106cefaae1SJack Meng 	uchar_t		    ip_addr[16];
1116cefaae1SJack Meng 	char		    Subnet_Mask_Prefix;
1126cefaae1SJack Meng 	char		    Origin;
1136cefaae1SJack Meng 	uchar_t		    Gateway[16];
1146cefaae1SJack Meng 	uchar_t		    Primary_dns[16];
1156cefaae1SJack Meng 	uchar_t		    Secondary_dns[16];
1166cefaae1SJack Meng 	uchar_t		    dhcp[16];
1176cefaae1SJack Meng 	ushort_t	    vlan;
1186cefaae1SJack Meng 	char		    mac[6];
1196cefaae1SJack Meng 	ushort_t	    pci_BDF;
1206cefaae1SJack Meng 	ushort_t	    Hostname_len;
1216cefaae1SJack Meng 	ushort_t	    Hostname_offset;
1226cefaae1SJack Meng }iscsi_ibft_nic_t;
1236cefaae1SJack Meng 
1246cefaae1SJack Meng typedef struct iSCSI_ibft_target {
1256cefaae1SJack Meng 	iscsi_ibft_hdr_t    header;
1266cefaae1SJack Meng 	uchar_t		    ip_addr[16];
1276cefaae1SJack Meng 	ushort_t	    port;
1286cefaae1SJack Meng 	uchar_t		    boot_lun[8];
1296cefaae1SJack Meng 	uchar_t		    chap_type;
1306cefaae1SJack Meng 	uchar_t		    nic_association;
1316cefaae1SJack Meng 	ushort_t	    target_name_len;
1326cefaae1SJack Meng 	ushort_t	    target_name_offset;
1336cefaae1SJack Meng 	ushort_t	    chap_name_len;
1346cefaae1SJack Meng 	ushort_t	    chap_name_offset;
1356cefaae1SJack Meng 	ushort_t	    chap_secret_len;
1366cefaae1SJack Meng 	ushort_t	    chap_secret_offset;
1376cefaae1SJack Meng 	ushort_t	    rev_chap_name_len;
1386cefaae1SJack Meng 	ushort_t	    rev_chap_name_offset;
1396cefaae1SJack Meng 	ushort_t	    rev_chap_secret_len;
1406cefaae1SJack Meng 	ushort_t	    rev_chap_secret_offset;
1416cefaae1SJack Meng }iscsi_ibft_tgt_t;
1426cefaae1SJack Meng 
1436cefaae1SJack Meng #define	ISCSI_IBFT_LOWER_ADDR		0x80000	    /* 512K */
1446cefaae1SJack Meng #define	ISCSI_IBFT_HIGHER_ADDR		0x100000    /* 1024K */
1456cefaae1SJack Meng #define	ISCSI_IBFT_SIGNATRUE		"iBFT"
1466cefaae1SJack Meng #define	ISCSI_IBFT_SIGNATURE_LEN	4
1476cefaae1SJack Meng #define	ISCSI_IBFT_TBL_BUF_LEN		1024
1486cefaae1SJack Meng #define	ISCSI_IBFT_ALIGNED		16
1496cefaae1SJack Meng #define	ISCSI_IBFT_CTL_OFFSET		48
1506cefaae1SJack Meng 
1516cefaae1SJack Meng #define	IBFT_BLOCK_VALID_YES		0x01	/* bit 0 */
1526cefaae1SJack Meng #define	IBFT_FIRMWARE_BOOT_SELECTED	0x02	/* bit 1 */
1536cefaae1SJack Meng #define	IBFT_USE_RADIUS_CHAP		0x04	/* bit 2 */
1546cefaae1SJack Meng #define	IBFT_USE_GLOBLE			0x04	/* NIC structure */
1556cefaae1SJack Meng #define	IBFT_USE_RADIUS_RHCAP		0x08	/* bit 3 */
1566cefaae1SJack Meng 
1576cefaae1SJack Meng /*
1586cefaae1SJack Meng  * Currently, we only support initiator offset, NIC0 offset, Target0 offset,
1596cefaae1SJack Meng  * NIC1 offset and Target1 offset. So the length is 5. If we want to support
1606cefaae1SJack Meng  * extensions, we should change this number.
1616cefaae1SJack Meng  */
1626cefaae1SJack Meng #define	IBFT_OFFSET_BUF_LEN		5
1636cefaae1SJack Meng #define	IPV4_OFFSET			12
1646cefaae1SJack Meng 
1656cefaae1SJack Meng #define	IBFT_INVALID_MSG		"Invalid iBFT table 0x%x"
166474eb465Svitezslav batrla - Sun Microsystems - Prague Czech Republic #define	IBFT_NOPROBE_MSG		"iSCSI boot is disabled"
1676cefaae1SJack Meng 
1686cefaae1SJack Meng typedef enum ibft_status {
1696cefaae1SJack Meng 	IBFT_STATUS_OK = 0,
1706cefaae1SJack Meng 	/* General error */
1716cefaae1SJack Meng 	IBFT_STATUS_ERR,
1726cefaae1SJack Meng 	/* Bad header */
1736cefaae1SJack Meng 	IBFT_STATUS_BADHDR,
1746cefaae1SJack Meng 	/* Bad control ID */
1756cefaae1SJack Meng 	IBFT_STATUS_BADCID,
1766cefaae1SJack Meng 	/* Bad ip addr */
1776cefaae1SJack Meng 	IBFT_STATUS_BADIP,
1786cefaae1SJack Meng 	/* Bad af */
1796cefaae1SJack Meng 	IBFT_STATUS_BADAF,
1806cefaae1SJack Meng 	/* Bad chap name */
1816cefaae1SJack Meng 	IBFT_STATUS_BADCHAPNAME,
1826cefaae1SJack Meng 	/* Bad chap secret */
1836cefaae1SJack Meng 	IBFT_STATUS_BADCHAPSEC,
1846cefaae1SJack Meng 	/* Bad checksum */
1856cefaae1SJack Meng 	IBFT_STATUS_BADCHECKSUM,
1866cefaae1SJack Meng 	/* Low memory */
1876cefaae1SJack Meng 	IBFT_STATUS_LOWMEM,
1886cefaae1SJack Meng 	/* No table */
1896cefaae1SJack Meng 	IBFT_STATUS_NOTABLE
1906cefaae1SJack Meng } ibft_status_t;
1916cefaae1SJack Meng 
1926cefaae1SJack Meng extern void *memset(void *s, int c, size_t n);
1936cefaae1SJack Meng extern int memcmp(const void *s1, const void *s2, size_t n);
1946cefaae1SJack Meng extern void bcopy(const void *s1, void *s2, size_t n);
1956cefaae1SJack Meng extern void iscsi_print_boot_property();
1966cefaae1SJack Meng 
197474eb465Svitezslav batrla - Sun Microsystems - Prague Czech Republic int ibft_noprobe = 0;
1986cefaae1SJack Meng ib_boot_prop_t boot_property;		/* static allocated */
1996cefaae1SJack Meng extern ib_boot_prop_t *iscsiboot_prop;	/* to be filled */
2006cefaae1SJack Meng 
2016cefaae1SJack Meng static ibft_status_t iscsi_parse_ibft_control(iscsi_ibft_ctl_t *ctl_hdr,
2026cefaae1SJack Meng     ushort_t *iscsi_offset_buf);
2036cefaae1SJack Meng 
2046cefaae1SJack Meng static ibft_status_t iscsi_parse_ibft_initiator(char *begin_of_ibft,
2056cefaae1SJack Meng     iscsi_ibft_initiator_t *initiator);
2066cefaae1SJack Meng 
2076cefaae1SJack Meng static ibft_status_t iscsi_parse_ibft_NIC(iscsi_ibft_nic_t *nicp);
2086cefaae1SJack Meng 
2096cefaae1SJack Meng static ibft_status_t iscsi_parse_ibft_target(char *begin_of_ibft,
2106cefaae1SJack Meng     iscsi_ibft_tgt_t *tgtp);
2116cefaae1SJack Meng 
2126cefaae1SJack Meng 
2136cefaae1SJack Meng /*
2146cefaae1SJack Meng  * Return value:
2156cefaae1SJack Meng  * Success: IBFT_STATUS_OK
2166cefaae1SJack Meng  * Fail: IBFT_STATUS_BADCHECKSUM
2176cefaae1SJack Meng  */
2186cefaae1SJack Meng static ibft_status_t
iscsi_ibft_hdr_checksum(iscsi_ibft_tbl_hdr_t * tbl_hdr)2196cefaae1SJack Meng iscsi_ibft_hdr_checksum(iscsi_ibft_tbl_hdr_t *tbl_hdr)
2206cefaae1SJack Meng {
2216cefaae1SJack Meng 	uchar_t	checksum    =	0;
2226cefaae1SJack Meng 	uchar_t	*start	    =	NULL;
2236cefaae1SJack Meng 	int	length	    =	0;
2246cefaae1SJack Meng 	int	i	    =	0;
2256cefaae1SJack Meng 
2266cefaae1SJack Meng 	if (tbl_hdr == NULL) {
2276cefaae1SJack Meng 		return (IBFT_STATUS_BADHDR);
2286cefaae1SJack Meng 	}
2296cefaae1SJack Meng 
2306cefaae1SJack Meng 	length = tbl_hdr->Length;
2316cefaae1SJack Meng 	start = (uchar_t *)tbl_hdr;
2326cefaae1SJack Meng 
2336cefaae1SJack Meng 	for (i = 0; i < length; i++) {
2346cefaae1SJack Meng 		checksum = checksum + start[i];
2356cefaae1SJack Meng 	}
2366cefaae1SJack Meng 
2376cefaae1SJack Meng 	if (!checksum)
2386cefaae1SJack Meng 		return (IBFT_STATUS_OK);
2396cefaae1SJack Meng 	else
2406cefaae1SJack Meng 		return (IBFT_STATUS_BADCHECKSUM);
2416cefaae1SJack Meng }
2426cefaae1SJack Meng 
2436cefaae1SJack Meng /*
2446cefaae1SJack Meng  * Now we only support one control structure in the IBFT.
2456cefaae1SJack Meng  * So there is no Control ID here.
2466cefaae1SJack Meng  */
2476cefaae1SJack Meng static ibft_status_t
iscsi_parse_ibft_structure(char * begin_of_ibft,char * buf)2486cefaae1SJack Meng iscsi_parse_ibft_structure(char *begin_of_ibft, char *buf)
2496cefaae1SJack Meng {
2506cefaae1SJack Meng 	iscsi_ibft_hdr_t	*hdr	=   NULL;
2516cefaae1SJack Meng 	ibft_status_t		ret	=   IBFT_STATUS_OK;
2526cefaae1SJack Meng 
2536cefaae1SJack Meng 	if (buf == NULL) {
2546cefaae1SJack Meng 		return (IBFT_STATUS_ERR);
2556cefaae1SJack Meng 	}
2566cefaae1SJack Meng 
2576cefaae1SJack Meng 	hdr = (iscsi_ibft_hdr_t *)buf;
2586cefaae1SJack Meng 	switch (hdr->Structure_id) {
2596cefaae1SJack Meng 		case Initiator:
2606cefaae1SJack Meng 			ret = iscsi_parse_ibft_initiator(
2616cefaae1SJack Meng 			    begin_of_ibft,
2626cefaae1SJack Meng 			    (iscsi_ibft_initiator_t *)buf);
2636cefaae1SJack Meng 			break;
2646cefaae1SJack Meng 		case Nic:
2656cefaae1SJack Meng 			ret = iscsi_parse_ibft_NIC(
2666cefaae1SJack Meng 			    (iscsi_ibft_nic_t *)buf);
2676cefaae1SJack Meng 			break;
2686cefaae1SJack Meng 		case Target:
2696cefaae1SJack Meng 			ret = iscsi_parse_ibft_target(
2706cefaae1SJack Meng 			    begin_of_ibft,
2716cefaae1SJack Meng 			    (iscsi_ibft_tgt_t *)buf);
2726cefaae1SJack Meng 			break;
2736cefaae1SJack Meng 		default:
2746cefaae1SJack Meng 			ret = IBFT_STATUS_BADHDR;
2756cefaae1SJack Meng 			break;
2766cefaae1SJack Meng 	}
2776cefaae1SJack Meng 
2786cefaae1SJack Meng 	return (ret);
2796cefaae1SJack Meng }
2806cefaae1SJack Meng 
2816cefaae1SJack Meng /*
2826cefaae1SJack Meng  * Parse the iBFT table
2836cefaae1SJack Meng  * return IBFT_STATUS_OK upon sucess
2846cefaae1SJack Meng  */
2856cefaae1SJack Meng static ibft_status_t
iscsi_parse_ibft_tbl(iscsi_ibft_tbl_hdr_t * tbl_hdr)2866cefaae1SJack Meng iscsi_parse_ibft_tbl(iscsi_ibft_tbl_hdr_t *tbl_hdr)
2876cefaae1SJack Meng {
2886cefaae1SJack Meng 	char		*outbuf	    =	NULL;
2896cefaae1SJack Meng 	int		i	    =	0;
2906cefaae1SJack Meng 	ibft_status_t	ret	    =	IBFT_STATUS_OK;
2916cefaae1SJack Meng 	ushort_t	iscsi_offset_buf[IBFT_OFFSET_BUF_LEN] = {0};
2926cefaae1SJack Meng 
2936cefaae1SJack Meng 	if (tbl_hdr == NULL) {
2946cefaae1SJack Meng 		return (IBFT_STATUS_ERR);
2956cefaae1SJack Meng 	}
2966cefaae1SJack Meng 
2976cefaae1SJack Meng 	if (iscsi_ibft_hdr_checksum(tbl_hdr) != IBFT_STATUS_OK) {
2986cefaae1SJack Meng 		return (IBFT_STATUS_BADCHECKSUM);
2996cefaae1SJack Meng 	}
3006cefaae1SJack Meng 
3016cefaae1SJack Meng 	outbuf = (char *)tbl_hdr;
3026cefaae1SJack Meng 
3036cefaae1SJack Meng 	ret = iscsi_parse_ibft_control(
3046cefaae1SJack Meng 	    (iscsi_ibft_ctl_t *)&outbuf[ISCSI_IBFT_CTL_OFFSET],
3056cefaae1SJack Meng 	    iscsi_offset_buf);
3066cefaae1SJack Meng 
3076cefaae1SJack Meng 	if (ret == IBFT_STATUS_OK) {
3086cefaae1SJack Meng 		ret = IBFT_STATUS_ERR;
3096cefaae1SJack Meng 		for (i = 0; i < IBFT_OFFSET_BUF_LEN; i++) {
3106cefaae1SJack Meng 			if (iscsi_offset_buf[i] != 0) {
3116cefaae1SJack Meng 				ret = iscsi_parse_ibft_structure(
3126cefaae1SJack Meng 				    (char *)tbl_hdr,
3136cefaae1SJack Meng 				    (char *)tbl_hdr +
3146cefaae1SJack Meng 				    iscsi_offset_buf[i]);
3156cefaae1SJack Meng 				if (ret != IBFT_STATUS_OK) {
3166cefaae1SJack Meng 					return (ret);
3176cefaae1SJack Meng 				}
3186cefaae1SJack Meng 			}
3196cefaae1SJack Meng 		}
3206cefaae1SJack Meng 	}
3216cefaae1SJack Meng 
3226cefaae1SJack Meng 	return (ret);
3236cefaae1SJack Meng }
3246cefaae1SJack Meng 
3256cefaae1SJack Meng static ibft_status_t
iscsi_parse_ibft_control(iscsi_ibft_ctl_t * ctl_hdr,ushort_t * iscsi_offset_buf)3266cefaae1SJack Meng iscsi_parse_ibft_control(iscsi_ibft_ctl_t *ctl_hdr,
3276cefaae1SJack Meng     ushort_t	*iscsi_offset_buf)
3286cefaae1SJack Meng {
3296cefaae1SJack Meng 	int	    i		=	0;
3306cefaae1SJack Meng 	ushort_t    *offsetp	=	NULL;
3316cefaae1SJack Meng 
3326cefaae1SJack Meng 	if (ctl_hdr == NULL) {
3336cefaae1SJack Meng 		return (IBFT_STATUS_BADHDR);
3346cefaae1SJack Meng 	}
3356cefaae1SJack Meng 
3366cefaae1SJack Meng 	if (ctl_hdr->header.Structure_id != Control) {
3376cefaae1SJack Meng 		return (IBFT_STATUS_BADCID);
3386cefaae1SJack Meng 	}
3396cefaae1SJack Meng 
3406cefaae1SJack Meng 	/*
3416cefaae1SJack Meng 	 * Copy the offsets to offset buffer.
3426cefaae1SJack Meng 	 */
3436cefaae1SJack Meng 	for (offsetp = &(ctl_hdr->Initiator_offset); i < IBFT_OFFSET_BUF_LEN;
3446cefaae1SJack Meng 	    offsetp++) {
3456cefaae1SJack Meng 		iscsi_offset_buf[i++] = *offsetp;
3466cefaae1SJack Meng 	}
3476cefaae1SJack Meng 
3486cefaae1SJack Meng 	return (IBFT_STATUS_OK);
3496cefaae1SJack Meng }
3506cefaae1SJack Meng 
3516cefaae1SJack Meng /*
3526cefaae1SJack Meng  * We only copy the "Firmare Boot Selseted" and valid initiator
3536cefaae1SJack Meng  * to the boot property.
3546cefaae1SJack Meng  */
3556cefaae1SJack Meng static ibft_status_t
iscsi_parse_ibft_initiator(char * begin_of_ibft,iscsi_ibft_initiator_t * initiator)3566cefaae1SJack Meng iscsi_parse_ibft_initiator(char *begin_of_ibft,
3576cefaae1SJack Meng     iscsi_ibft_initiator_t *initiator)
3586cefaae1SJack Meng {
3596cefaae1SJack Meng 	if (initiator == NULL) {
3606cefaae1SJack Meng 		return (IBFT_STATUS_ERR);
3616cefaae1SJack Meng 	}
3626cefaae1SJack Meng 
3636cefaae1SJack Meng 	if (initiator->header.Structure_id != Initiator) {
3646cefaae1SJack Meng 		return (IBFT_STATUS_BADHDR);
3656cefaae1SJack Meng 	}
3666cefaae1SJack Meng 
3676cefaae1SJack Meng 	if ((initiator->header.Flags & IBFT_FIRMWARE_BOOT_SELECTED) &&
3686cefaae1SJack Meng 	    (initiator->header.Flags & IBFT_BLOCK_VALID_YES)) {
3696cefaae1SJack Meng 		/*
3706cefaae1SJack Meng 		 * If the initiator name exists, we will copy it to our own
3716cefaae1SJack Meng 		 * property structure
3726cefaae1SJack Meng 		 */
3736cefaae1SJack Meng 		if (initiator->ini_name_len != 0) {
3746cefaae1SJack Meng 			boot_property.boot_init.ini_name =
3756cefaae1SJack Meng 			    (uchar_t *)kmem_zalloc(
3766cefaae1SJack Meng 			    initiator->ini_name_len + 1, KM_SLEEP);
377*dedec472SJack Meng 			boot_property.boot_init.ini_name_len =
378*dedec472SJack Meng 			    initiator->ini_name_len + 1;
3796cefaae1SJack Meng 			(void) snprintf(
3806cefaae1SJack Meng 			    (char *)boot_property.boot_init.ini_name,
3816cefaae1SJack Meng 			    initiator->ini_name_len + 1, "%s",
3826cefaae1SJack Meng 			    begin_of_ibft + initiator->ini_name_offset);
3836cefaae1SJack Meng 		}
3846cefaae1SJack Meng 	}
3856cefaae1SJack Meng 	return (IBFT_STATUS_OK);
3866cefaae1SJack Meng }
3876cefaae1SJack Meng 
3886cefaae1SJack Meng static ibft_status_t
iscsi_parse_ipaddr(uchar_t * source,char * dest,int * af)3896cefaae1SJack Meng iscsi_parse_ipaddr(uchar_t *source, char *dest, int *af)
3906cefaae1SJack Meng {
3916cefaae1SJack Meng 	int i = 0;
3926cefaae1SJack Meng 
3936cefaae1SJack Meng 	if (source == NULL) {
3946cefaae1SJack Meng 		return (IBFT_STATUS_ERR);
3956cefaae1SJack Meng 	}
3966cefaae1SJack Meng 
3976cefaae1SJack Meng 	if (source[0] == 0x00 && source[1] == 0x00 &&
3986cefaae1SJack Meng 	    source[2] == 0x00 && source[3] == 0x00 &&
3996cefaae1SJack Meng 	    source[4] == 0x00 && source[5] == 0x00 &&
4006cefaae1SJack Meng 	    source[6] == 0x00 && source[7] == 0x00 &&
4016cefaae1SJack Meng 	    source[8] == 0x00 && source[9] == 0x00 &&
4026cefaae1SJack Meng 	    (source[10] == 0xff) && (source[11] == 0xff)) {
4036cefaae1SJack Meng 		/*
4046cefaae1SJack Meng 		 * IPv4 address
4056cefaae1SJack Meng 		 */
4066cefaae1SJack Meng 		if (dest != NULL) {
4076cefaae1SJack Meng 			(void) sprintf(dest, "%d.%d.%d.%d",
4086cefaae1SJack Meng 			    source[12], source[13], source[14], source[15]);
4096cefaae1SJack Meng 		}
4106cefaae1SJack Meng 		if (af != NULL) {
4116cefaae1SJack Meng 			*af = AF_INET;
4126cefaae1SJack Meng 		}
4136cefaae1SJack Meng 	} else {
4146cefaae1SJack Meng 		if (dest != NULL) {
4156cefaae1SJack Meng 			for (i = 0; i < 14; i = i + 2) {
4166cefaae1SJack Meng 				(void) sprintf(dest, "%02x%02x:", source[i],
4176cefaae1SJack Meng 				    source[i+1]);
4186cefaae1SJack Meng 				dest = dest + 5;
4196cefaae1SJack Meng 			}
4206cefaae1SJack Meng 			(void) sprintf(dest, "%02x%02x",
4216cefaae1SJack Meng 			    source[i], source[i+1]);
4226cefaae1SJack Meng 		}
4236cefaae1SJack Meng 		if (af != NULL) {
4246cefaae1SJack Meng 			*af = AF_INET6;
4256cefaae1SJack Meng 		}
4266cefaae1SJack Meng 	}
4276cefaae1SJack Meng 
4286cefaae1SJack Meng 	return (IBFT_STATUS_OK);
4296cefaae1SJack Meng }
4306cefaae1SJack Meng 
4316cefaae1SJack Meng /*
4326cefaae1SJack Meng  * Copy the ip address from ibft. If IPv4 is used, we should copy
4336cefaae1SJack Meng  * the address from 12th byte.
4346cefaae1SJack Meng  */
4356cefaae1SJack Meng static ibft_status_t
iscsi_copy_ibft_ipaddr(uchar_t * source,void * dest,int * af)4366cefaae1SJack Meng iscsi_copy_ibft_ipaddr(uchar_t *source, void *dest, int *af)
4376cefaae1SJack Meng {
4386cefaae1SJack Meng 	ibft_status_t	ret		=	IBFT_STATUS_OK;
4396cefaae1SJack Meng 	int		sin_family	=	0;
4406cefaae1SJack Meng 
4416cefaae1SJack Meng 	if (source == NULL || dest == NULL) {
4426cefaae1SJack Meng 		return (IBFT_STATUS_ERR);
4436cefaae1SJack Meng 	}
4446cefaae1SJack Meng 	ret = iscsi_parse_ipaddr(source, NULL, &sin_family);
4456cefaae1SJack Meng 	if (ret != 0) {
4466cefaae1SJack Meng 		return (IBFT_STATUS_BADIP);
4476cefaae1SJack Meng 	}
4486cefaae1SJack Meng 
4496cefaae1SJack Meng 	if (sin_family == AF_INET) {
4506cefaae1SJack Meng 		bcopy(source+IPV4_OFFSET, dest, sizeof (struct in_addr));
4516cefaae1SJack Meng 	} else if (sin_family == AF_INET6) {
4526cefaae1SJack Meng 		bcopy(source, dest, sizeof (struct in6_addr));
4536cefaae1SJack Meng 	} else {
4546cefaae1SJack Meng 		return (IBFT_STATUS_BADAF);
4556cefaae1SJack Meng 	}
4566cefaae1SJack Meng 
4576cefaae1SJack Meng 	if (af != NULL) {
4586cefaae1SJack Meng 		*af = sin_family;
4596cefaae1SJack Meng 	}
4606cefaae1SJack Meng 	return (IBFT_STATUS_OK);
4616cefaae1SJack Meng }
4626cefaae1SJack Meng 
4636cefaae1SJack Meng /*
4646cefaae1SJack Meng  * Maybe there are multiply NICs are available. We only copy the
4656cefaae1SJack Meng  * "Firmare Boot Selseted" and valid one to the boot property.
4666cefaae1SJack Meng  */
4676cefaae1SJack Meng static ibft_status_t
iscsi_parse_ibft_NIC(iscsi_ibft_nic_t * nicp)4686cefaae1SJack Meng iscsi_parse_ibft_NIC(iscsi_ibft_nic_t *nicp)
4696cefaae1SJack Meng {
4706cefaae1SJack Meng 	ibft_status_t	ret	=	IBFT_STATUS_OK;
4716cefaae1SJack Meng 	int		af	=	0;
4726cefaae1SJack Meng 
4736cefaae1SJack Meng 	if (nicp == NULL) {
4746cefaae1SJack Meng 		return (IBFT_STATUS_ERR);
4756cefaae1SJack Meng 	}
4766cefaae1SJack Meng 
4776cefaae1SJack Meng 	if (nicp->header.Structure_id != Nic) {
4786cefaae1SJack Meng 		return (IBFT_STATUS_ERR);
4796cefaae1SJack Meng 	}
4806cefaae1SJack Meng 
4816cefaae1SJack Meng 	if ((nicp->header.Flags & IBFT_FIRMWARE_BOOT_SELECTED) &&
4826cefaae1SJack Meng 	    (nicp->header.Flags & IBFT_BLOCK_VALID_YES)) {
4836cefaae1SJack Meng 		ret = iscsi_copy_ibft_ipaddr(nicp->ip_addr,
4846cefaae1SJack Meng 		    &boot_property.boot_nic.nic_ip_u, &af);
4856cefaae1SJack Meng 		if (ret != IBFT_STATUS_OK) {
4866cefaae1SJack Meng 			return (ret);
4876cefaae1SJack Meng 		}
4886cefaae1SJack Meng 
4896cefaae1SJack Meng 		boot_property.boot_nic.sin_family = af;
4906cefaae1SJack Meng 
4916cefaae1SJack Meng 		ret = iscsi_copy_ibft_ipaddr(nicp->Gateway,
4926cefaae1SJack Meng 		    &boot_property.boot_nic.nic_gw_u, NULL);
4936cefaae1SJack Meng 		if (ret != IBFT_STATUS_OK) {
4946cefaae1SJack Meng 			return (ret);
4956cefaae1SJack Meng 		}
4966cefaae1SJack Meng 
4976cefaae1SJack Meng 		ret = iscsi_copy_ibft_ipaddr(nicp->dhcp,
4986cefaae1SJack Meng 		    &boot_property.boot_nic.nic_dhcp_u, NULL);
4996cefaae1SJack Meng 		if (ret != IBFT_STATUS_OK) {
5006cefaae1SJack Meng 			return (ret);
5016cefaae1SJack Meng 		}
5026cefaae1SJack Meng 
5036cefaae1SJack Meng 		bcopy(nicp->mac, boot_property.boot_nic.nic_mac, 6);
5046cefaae1SJack Meng 		boot_property.boot_nic.sub_mask_prefix =
5056cefaae1SJack Meng 		    nicp->Subnet_Mask_Prefix;
5066cefaae1SJack Meng 	}
5076cefaae1SJack Meng 
5086cefaae1SJack Meng 	return (IBFT_STATUS_OK);
5096cefaae1SJack Meng }
5106cefaae1SJack Meng 
5116cefaae1SJack Meng /*
5126cefaae1SJack Meng  * Maybe there are multiply targets are available. We only copy the
5136cefaae1SJack Meng  * "Firmare Boot Selseted" and valid one to the boot property.
5146cefaae1SJack Meng  */
5156cefaae1SJack Meng static ibft_status_t
iscsi_parse_ibft_target(char * begin_of_ibft,iscsi_ibft_tgt_t * tgtp)5166cefaae1SJack Meng iscsi_parse_ibft_target(char *begin_of_ibft, iscsi_ibft_tgt_t *tgtp)
5176cefaae1SJack Meng {
5186cefaae1SJack Meng 	char		*tmp	=   NULL;
5196cefaae1SJack Meng 	int		af	=   0;
5206cefaae1SJack Meng 	ibft_status_t	ret	=   IBFT_STATUS_OK;
5216cefaae1SJack Meng 
5226cefaae1SJack Meng 	if (tgtp == NULL) {
5236cefaae1SJack Meng 		return (IBFT_STATUS_ERR);
5246cefaae1SJack Meng 	}
5256cefaae1SJack Meng 
5266cefaae1SJack Meng 	if (tgtp->header.Structure_id != Target) {
5276cefaae1SJack Meng 		return (IBFT_STATUS_BADHDR);
5286cefaae1SJack Meng 	}
5296cefaae1SJack Meng 
5306cefaae1SJack Meng 	if ((tgtp->header.Flags & IBFT_FIRMWARE_BOOT_SELECTED) &&
5316cefaae1SJack Meng 	    (tgtp->header.Flags & IBFT_BLOCK_VALID_YES)) {
5326cefaae1SJack Meng 		/*
5336cefaae1SJack Meng 		 * Get Target Address
5346cefaae1SJack Meng 		 */
5356cefaae1SJack Meng 		ret = iscsi_copy_ibft_ipaddr(tgtp->ip_addr,
5366cefaae1SJack Meng 		    &boot_property.boot_tgt.tgt_ip_u, &af);
5376cefaae1SJack Meng 		if (ret != IBFT_STATUS_OK) {
5386cefaae1SJack Meng 			return (ret);
5396cefaae1SJack Meng 		}
5406cefaae1SJack Meng 		boot_property.boot_tgt.sin_family = af;
5416cefaae1SJack Meng 		/*
5426cefaae1SJack Meng 		 * Get Target Name
5436cefaae1SJack Meng 		 */
5446cefaae1SJack Meng 		if (tgtp->target_name_len != 0) {
5456cefaae1SJack Meng 			boot_property.boot_tgt.tgt_name =
5466cefaae1SJack Meng 			    (uchar_t *)kmem_zalloc(tgtp->target_name_len + 1,
5476cefaae1SJack Meng 			    KM_SLEEP);
548*dedec472SJack Meng 			boot_property.boot_tgt.tgt_name_len =
549*dedec472SJack Meng 			    tgtp->target_name_len + 1;
5506cefaae1SJack Meng 			(void) snprintf(
5516cefaae1SJack Meng 			    (char *)boot_property.boot_tgt.tgt_name,
5526cefaae1SJack Meng 			    tgtp->target_name_len + 1, "%s",
5536cefaae1SJack Meng 			    begin_of_ibft + tgtp->target_name_offset);
5546cefaae1SJack Meng 		} else {
5556cefaae1SJack Meng 			boot_property.boot_tgt.tgt_name = NULL;
5566cefaae1SJack Meng 		}
5576cefaae1SJack Meng 
5586cefaae1SJack Meng 		/* Get Dest Port */
5596cefaae1SJack Meng 		boot_property.boot_tgt.tgt_port = tgtp->port;
5606cefaae1SJack Meng 
5616cefaae1SJack Meng 		boot_property.boot_tgt.lun_online = 0;
5626cefaae1SJack Meng 
5636cefaae1SJack Meng 		/*
5646cefaae1SJack Meng 		 * Get CHAP secret and name.
5656cefaae1SJack Meng 		 */
5666cefaae1SJack Meng 		if (tgtp->chap_type != NO_CHAP) {
5676cefaae1SJack Meng 			if (tgtp->chap_name_len != 0) {
5686cefaae1SJack Meng 				boot_property.boot_init.ini_chap_name =
5696cefaae1SJack Meng 				    (uchar_t *)kmem_zalloc(
5706cefaae1SJack Meng 				    tgtp->chap_name_len + 1,
5716cefaae1SJack Meng 				    KM_SLEEP);
572*dedec472SJack Meng 				boot_property.boot_init.ini_chap_name_len =
573*dedec472SJack Meng 				    tgtp->chap_name_len + 1;
5746cefaae1SJack Meng 				tmp = (char *)
5756cefaae1SJack Meng 				    boot_property.boot_init.ini_chap_name;
5766cefaae1SJack Meng 				(void) snprintf(
5776cefaae1SJack Meng 				    tmp,
5786cefaae1SJack Meng 				    tgtp->chap_name_len + 1, "%s",
5796cefaae1SJack Meng 				    begin_of_ibft + tgtp->chap_name_offset);
5806cefaae1SJack Meng 			} else {
5816cefaae1SJack Meng 				/*
5826cefaae1SJack Meng 				 * Just set NULL, initiator is able to deal
5836cefaae1SJack Meng 				 * with this
5846cefaae1SJack Meng 				 */
5856cefaae1SJack Meng 				boot_property.boot_init.ini_chap_name = NULL;
5866cefaae1SJack Meng 			}
5876cefaae1SJack Meng 
5886cefaae1SJack Meng 			if (tgtp->chap_secret_len != 0) {
5896cefaae1SJack Meng 				boot_property.boot_init.ini_chap_sec =
5906cefaae1SJack Meng 				    (uchar_t *)kmem_zalloc(
5916cefaae1SJack Meng 				    tgtp->chap_secret_len + 1,
5926cefaae1SJack Meng 				    KM_SLEEP);
593*dedec472SJack Meng 				boot_property.boot_init.ini_chap_sec_len =
594*dedec472SJack Meng 				    tgtp->chap_secret_len + 1;
5956cefaae1SJack Meng 				bcopy(begin_of_ibft +
5966cefaae1SJack Meng 				    tgtp->chap_secret_offset,
5976cefaae1SJack Meng 				    boot_property.boot_init.ini_chap_sec,
5986cefaae1SJack Meng 				    tgtp->chap_secret_len);
5996cefaae1SJack Meng 			} else {
6006cefaae1SJack Meng 				boot_property.boot_init.ini_chap_sec = NULL;
6016cefaae1SJack Meng 				return (IBFT_STATUS_ERR);
6026cefaae1SJack Meng 			}
6036cefaae1SJack Meng 
6046cefaae1SJack Meng 			if (tgtp->chap_type == Mutual_CHAP) {
6056cefaae1SJack Meng 				if (tgtp->rev_chap_name_len != 0) {
6066cefaae1SJack Meng 					boot_property.boot_tgt.tgt_chap_name =
6076cefaae1SJack Meng 					    (uchar_t *)kmem_zalloc(
608*dedec472SJack Meng 					    tgtp->rev_chap_name_len + 1,
6096cefaae1SJack Meng 					    KM_SLEEP);
610*dedec472SJack Meng 					boot_property.boot_tgt.tgt_chap_name_len
611*dedec472SJack Meng 					    = tgtp->rev_chap_name_len + 1;
6126cefaae1SJack Meng #define	TGT_CHAP_NAME	boot_property.boot_tgt.tgt_chap_name
6136cefaae1SJack Meng 					tmp = (char *)TGT_CHAP_NAME;
6146cefaae1SJack Meng #undef	TGT_CHAP_NAME
6156cefaae1SJack Meng 					(void) snprintf(
6166cefaae1SJack Meng 					    tmp,
617*dedec472SJack Meng 					    tgtp->rev_chap_name_len + 1,
6186cefaae1SJack Meng 					    "%s",
6196cefaae1SJack Meng 					    begin_of_ibft +
6206cefaae1SJack Meng 					    tgtp->rev_chap_name_offset);
6216cefaae1SJack Meng 				} else {
6226cefaae1SJack Meng 					/*
6236cefaae1SJack Meng 					 * Just set NULL, initiator is able
6246cefaae1SJack Meng 					 * to deal with this
6256cefaae1SJack Meng 					 */
6266cefaae1SJack Meng 					boot_property.boot_tgt.tgt_chap_name =
6276cefaae1SJack Meng 					    NULL;
6286cefaae1SJack Meng 				}
6296cefaae1SJack Meng 
6306cefaae1SJack Meng 				if (tgtp->rev_chap_secret_len != 0) {
6316cefaae1SJack Meng 					boot_property.boot_tgt.tgt_chap_sec =
6326cefaae1SJack Meng 					    (uchar_t *)kmem_zalloc(
6336cefaae1SJack Meng 					    tgtp->rev_chap_secret_len + 1,
6346cefaae1SJack Meng 					    KM_SLEEP);
635*dedec472SJack Meng 					boot_property.boot_tgt.tgt_chap_sec_len
636*dedec472SJack Meng 					    = tgtp->rev_chap_secret_len + 1;
6376cefaae1SJack Meng 					tmp = (char *)
6386cefaae1SJack Meng 					    boot_property.boot_tgt.tgt_chap_sec;
6396cefaae1SJack Meng 					(void) snprintf(
6406cefaae1SJack Meng 					    tmp,
6416cefaae1SJack Meng 					    tgtp->rev_chap_secret_len + 1,
6426cefaae1SJack Meng 					    "%s",
6436cefaae1SJack Meng 					    begin_of_ibft +
6446cefaae1SJack Meng 					    tgtp->chap_secret_offset);
6456cefaae1SJack Meng 				} else {
6466cefaae1SJack Meng 					boot_property.boot_tgt.tgt_chap_sec =
6476cefaae1SJack Meng 					    NULL;
6486cefaae1SJack Meng 					return (IBFT_STATUS_BADCHAPSEC);
6496cefaae1SJack Meng 				}
6506cefaae1SJack Meng 			}
6516cefaae1SJack Meng 		} else {
6526cefaae1SJack Meng 			boot_property.boot_init.ini_chap_name = NULL;
6536cefaae1SJack Meng 			boot_property.boot_init.ini_chap_sec = NULL;
6546cefaae1SJack Meng 		}
6556cefaae1SJack Meng 
6566cefaae1SJack Meng 		/*
6576cefaae1SJack Meng 		 * Get Boot LUN
6586cefaae1SJack Meng 		 */
6596cefaae1SJack Meng 		(void) bcopy(tgtp->boot_lun,
6606cefaae1SJack Meng 		    boot_property.boot_tgt.tgt_boot_lun, 8);
6616cefaae1SJack Meng 	}
6626cefaae1SJack Meng 
6636cefaae1SJack Meng 	return (IBFT_STATUS_OK);
6646cefaae1SJack Meng }
6656cefaae1SJack Meng 
6666cefaae1SJack Meng /*
6676cefaae1SJack Meng  * This function is used for scanning iBFT from the physical memory.
6686cefaae1SJack Meng  * Return Value:
6696cefaae1SJack Meng  * IBFT_STATUS_OK
6706cefaae1SJack Meng  * IBFT_STATUS_ERR
6716cefaae1SJack Meng  */
6726cefaae1SJack Meng static ibft_status_t
iscsi_scan_ibft_tbl(char * ibft_tbl_buf)6736cefaae1SJack Meng iscsi_scan_ibft_tbl(char *ibft_tbl_buf)
6746cefaae1SJack Meng {
6756cefaae1SJack Meng 	int		start;
6766cefaae1SJack Meng 	void		*va		= NULL;
6776cefaae1SJack Meng 	int		*len 		= NULL;
6786cefaae1SJack Meng 	ibft_status_t	ret		= IBFT_STATUS_NOTABLE;
6796cefaae1SJack Meng 
6806cefaae1SJack Meng 	for (start = ISCSI_IBFT_LOWER_ADDR; start < ISCSI_IBFT_HIGHER_ADDR;
6816cefaae1SJack Meng 	    start = start + ISCSI_IBFT_ALIGNED) {
6826cefaae1SJack Meng 		va = (void *)psm_map((paddr_t)(start&0xffffffff),
6836cefaae1SJack Meng 		    ISCSI_IBFT_SIGNATURE_LEN,
6846cefaae1SJack Meng 		    PROT_READ);
6856cefaae1SJack Meng 
6866cefaae1SJack Meng 		if (va == NULL) {
6876cefaae1SJack Meng 			continue;
6886cefaae1SJack Meng 		}
6896cefaae1SJack Meng 		if (memcmp(va, ISCSI_IBFT_SIGNATRUE,
6906cefaae1SJack Meng 		    ISCSI_IBFT_SIGNATURE_LEN) == 0) {
6916cefaae1SJack Meng 			ret = IBFT_STATUS_ERR;
6926cefaae1SJack Meng 			/* Acquire table length */
6936cefaae1SJack Meng 			len = (int *)psm_map(
6946cefaae1SJack Meng 			    (paddr_t)((start+\
6956cefaae1SJack Meng 			    ISCSI_IBFT_SIGNATURE_LEN)&0xffffffff),
6966cefaae1SJack Meng 			    ISCSI_IBFT_SIGNATURE_LEN, PROT_READ);
6976cefaae1SJack Meng 			if (len == NULL) {
6986cefaae1SJack Meng 				psm_unmap((caddr_t)va,
6996cefaae1SJack Meng 				    ISCSI_IBFT_SIGNATURE_LEN);
7006cefaae1SJack Meng 				continue;
7016cefaae1SJack Meng 			}
7026cefaae1SJack Meng 			if (ISCSI_IBFT_LOWER_ADDR + *len <
7036cefaae1SJack Meng 			    ISCSI_IBFT_HIGHER_ADDR - 1) {
7046cefaae1SJack Meng 				psm_unmap(va,
7056cefaae1SJack Meng 				    ISCSI_IBFT_SIGNATURE_LEN);
7066cefaae1SJack Meng 				va = psm_map((paddr_t)(start&0xffffffff),
7076cefaae1SJack Meng 				    *len,
7086cefaae1SJack Meng 				    PROT_READ);
7096cefaae1SJack Meng 				if (va != NULL) {
7106cefaae1SJack Meng 					/*
7116cefaae1SJack Meng 					 * Copy data to our own buffer
7126cefaae1SJack Meng 					 */
7136cefaae1SJack Meng 					bcopy(va, ibft_tbl_buf, *len);
7146cefaae1SJack Meng 					ret = IBFT_STATUS_OK;
7156cefaae1SJack Meng 				}
7166cefaae1SJack Meng 				psm_unmap((caddr_t)va, *len);
7176cefaae1SJack Meng 				psm_unmap((caddr_t)len,
7186cefaae1SJack Meng 				    ISCSI_IBFT_SIGNATURE_LEN);
7196cefaae1SJack Meng 				break;
7206cefaae1SJack Meng 			} else {
7216cefaae1SJack Meng 				psm_unmap((caddr_t)va,
7226cefaae1SJack Meng 				    ISCSI_IBFT_SIGNATURE_LEN);
7236cefaae1SJack Meng 				psm_unmap((caddr_t)len,
7246cefaae1SJack Meng 				    ISCSI_IBFT_SIGNATURE_LEN);
7256cefaae1SJack Meng 			}
7266cefaae1SJack Meng 		} else {
7276cefaae1SJack Meng 			psm_unmap((caddr_t)va, ISCSI_IBFT_SIGNATURE_LEN);
7286cefaae1SJack Meng 		}
7296cefaae1SJack Meng 	}
7306cefaae1SJack Meng 
7316cefaae1SJack Meng 	return (ret);
7326cefaae1SJack Meng }
7336cefaae1SJack Meng 
7346cefaae1SJack Meng /*
7356cefaae1SJack Meng  * Scan the ibft table and store the iSCSI boot properties
7366cefaae1SJack Meng  * If there is a valid table then set the iscsiboot_prop
7376cefaae1SJack Meng  * iBF should be off if the host is not intended
7386cefaae1SJack Meng  * to be booted from iSCSI disk
7396cefaae1SJack Meng  */
7406cefaae1SJack Meng void
ld_ib_prop()7416cefaae1SJack Meng ld_ib_prop()
7426cefaae1SJack Meng {
7436cefaae1SJack Meng 	ibft_status_t	ret	=   IBFT_STATUS_OK;
7446cefaae1SJack Meng 	char		*ibft_tbl_buf;
7456cefaae1SJack Meng 
746474eb465Svitezslav batrla - Sun Microsystems - Prague Czech Republic 	if (do_bsys_getproplen(NULL, "ibft-noprobe") > 0)
747474eb465Svitezslav batrla - Sun Microsystems - Prague Czech Republic 		ibft_noprobe = 1;
748474eb465Svitezslav batrla - Sun Microsystems - Prague Czech Republic 
749474eb465Svitezslav batrla - Sun Microsystems - Prague Czech Republic 	if (ibft_noprobe != 0) {
750474eb465Svitezslav batrla - Sun Microsystems - Prague Czech Republic 		/*
751474eb465Svitezslav batrla - Sun Microsystems - Prague Czech Republic 		 * Scanning for iBFT may conflict with devices which use memory
752474eb465Svitezslav batrla - Sun Microsystems - Prague Czech Republic 		 * in 640-1024KB of physical address space.  The iBFT
753474eb465Svitezslav batrla - Sun Microsystems - Prague Czech Republic 		 * specification suggests use of low RAM method - scanning
754474eb465Svitezslav batrla - Sun Microsystems - Prague Czech Republic 		 * physical memory 512-1024 KB for iBFT table.  However, the
755474eb465Svitezslav batrla - Sun Microsystems - Prague Czech Republic 		 * Upper Memory Area (UMA) 640-1024 KB may contain device
756474eb465Svitezslav batrla - Sun Microsystems - Prague Czech Republic 		 * memory or memory mapped I/O.  Although reading from I/O area
757474eb465Svitezslav batrla - Sun Microsystems - Prague Czech Republic 		 * is usually fine, the actual behavior depends on device
758474eb465Svitezslav batrla - Sun Microsystems - Prague Czech Republic 		 * implementation.  In some cases, the user may want to disable
759474eb465Svitezslav batrla - Sun Microsystems - Prague Czech Republic 		 * low RAM method and prevent reading from device I/O area.
760474eb465Svitezslav batrla - Sun Microsystems - Prague Czech Republic 		 *
761474eb465Svitezslav batrla - Sun Microsystems - Prague Czech Republic 		 * To disable low RAM method:
762474eb465Svitezslav batrla - Sun Microsystems - Prague Czech Republic 		 * 1) pass "-B ibft-noprobe=1" on kernel command line
763474eb465Svitezslav batrla - Sun Microsystems - Prague Czech Republic 		 * 2) add line "set ibft_noprobe=1" in /etc/system
764474eb465Svitezslav batrla - Sun Microsystems - Prague Czech Republic 		 */
765474eb465Svitezslav batrla - Sun Microsystems - Prague Czech Republic 		cmn_err(CE_NOTE, IBFT_NOPROBE_MSG);
766474eb465Svitezslav batrla - Sun Microsystems - Prague Czech Republic 		return;
767474eb465Svitezslav batrla - Sun Microsystems - Prague Czech Republic 	}
768474eb465Svitezslav batrla - Sun Microsystems - Prague Czech Republic 
7696cefaae1SJack Meng 	ibft_tbl_buf = (char *)kmem_zalloc(ISCSI_IBFT_TBL_BUF_LEN,
7706cefaae1SJack Meng 	    KM_SLEEP);
7716cefaae1SJack Meng 
7726cefaae1SJack Meng 	if (!ibft_tbl_buf) {
7736cefaae1SJack Meng 		/* Unlikely to happen */
7746cefaae1SJack Meng 		cmn_err(CE_NOTE, IBFT_INVALID_MSG,
7756cefaae1SJack Meng 		    IBFT_STATUS_LOWMEM);
7766cefaae1SJack Meng 		return;
7776cefaae1SJack Meng 	}
7786cefaae1SJack Meng 
7796cefaae1SJack Meng 	(void) memset(&boot_property, 0, sizeof (boot_property));
7806cefaae1SJack Meng 	if ((ret = iscsi_scan_ibft_tbl(ibft_tbl_buf)) ==
7816cefaae1SJack Meng 	    IBFT_STATUS_OK) {
7826cefaae1SJack Meng 		ret = iscsi_parse_ibft_tbl(
7836cefaae1SJack Meng 		    (iscsi_ibft_tbl_hdr_t *)ibft_tbl_buf);
7846cefaae1SJack Meng 		if (ret == IBFT_STATUS_OK) {
7856cefaae1SJack Meng 			iscsiboot_prop = &boot_property;
7866cefaae1SJack Meng 			iscsi_print_boot_property();
7876cefaae1SJack Meng 		} else {
7886cefaae1SJack Meng 			cmn_err(CE_NOTE, IBFT_INVALID_MSG, ret);
7896cefaae1SJack Meng 		}
7906cefaae1SJack Meng 	} else if (ret != IBFT_STATUS_NOTABLE) {
7916cefaae1SJack Meng 		cmn_err(CE_NOTE, IBFT_INVALID_MSG, ret);
7926cefaae1SJack Meng 	}
7936cefaae1SJack Meng 
7946cefaae1SJack Meng 	kmem_free(ibft_tbl_buf, ISCSI_IBFT_TBL_BUF_LEN);
7956cefaae1SJack Meng }
796