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