18194SJack.Meng@Sun.COM /* 28194SJack.Meng@Sun.COM * CDDL HEADER START 38194SJack.Meng@Sun.COM * 48194SJack.Meng@Sun.COM * The contents of this file are subject to the terms of the 58194SJack.Meng@Sun.COM * Common Development and Distribution License (the "License"). 68194SJack.Meng@Sun.COM * You may not use this file except in compliance with the License. 78194SJack.Meng@Sun.COM * 88194SJack.Meng@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 98194SJack.Meng@Sun.COM * or http://www.opensolaris.org/os/licensing. 108194SJack.Meng@Sun.COM * See the License for the specific language governing permissions 118194SJack.Meng@Sun.COM * and limitations under the License. 128194SJack.Meng@Sun.COM * 138194SJack.Meng@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each 148194SJack.Meng@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 158194SJack.Meng@Sun.COM * If applicable, add the following below this CDDL HEADER, with the 168194SJack.Meng@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying 178194SJack.Meng@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner] 188194SJack.Meng@Sun.COM * 198194SJack.Meng@Sun.COM * CDDL HEADER END 208194SJack.Meng@Sun.COM */ 218194SJack.Meng@Sun.COM 228194SJack.Meng@Sun.COM /* 23*8953SVitezslav.Batrla@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 248194SJack.Meng@Sun.COM * Use is subject to license terms. 258194SJack.Meng@Sun.COM */ 268194SJack.Meng@Sun.COM 278194SJack.Meng@Sun.COM /* 288194SJack.Meng@Sun.COM * This is the place to implement ld_ib_props() 298194SJack.Meng@Sun.COM * For x86 it is to load iBFT and costruct the global ib props 308194SJack.Meng@Sun.COM */ 318194SJack.Meng@Sun.COM 328194SJack.Meng@Sun.COM #include <sys/types.h> 338194SJack.Meng@Sun.COM #include <sys/cmn_err.h> 348194SJack.Meng@Sun.COM #include <sys/socket.h> 358194SJack.Meng@Sun.COM #include <netinet/in.h> 368194SJack.Meng@Sun.COM #include <sys/mman.h> 378194SJack.Meng@Sun.COM #include <sys/bootprops.h> 388194SJack.Meng@Sun.COM #include <sys/kmem.h> 398194SJack.Meng@Sun.COM #include <sys/psm.h> 40*8953SVitezslav.Batrla@Sun.COM #include <sys/bootconf.h> 418194SJack.Meng@Sun.COM 428194SJack.Meng@Sun.COM #ifndef NULL 438194SJack.Meng@Sun.COM #define NULL 0 448194SJack.Meng@Sun.COM #endif 458194SJack.Meng@Sun.COM 468194SJack.Meng@Sun.COM typedef enum ibft_structure_type { 478194SJack.Meng@Sun.COM Reserved = 0, 488194SJack.Meng@Sun.COM Control = 1, 498194SJack.Meng@Sun.COM Initiator = 2, 508194SJack.Meng@Sun.COM Nic = 3, 518194SJack.Meng@Sun.COM Target = 4, 528194SJack.Meng@Sun.COM Extensions = 5, 538194SJack.Meng@Sun.COM Type_End 548194SJack.Meng@Sun.COM }ibft_struct_type; 558194SJack.Meng@Sun.COM 568194SJack.Meng@Sun.COM typedef enum _chap_type { 578194SJack.Meng@Sun.COM NO_CHAP = 0, 588194SJack.Meng@Sun.COM CHAP = 1, 598194SJack.Meng@Sun.COM Mutual_CHAP = 2, 608194SJack.Meng@Sun.COM TYPE_UNKNOWN 618194SJack.Meng@Sun.COM }chap_type; 628194SJack.Meng@Sun.COM 638194SJack.Meng@Sun.COM typedef struct ibft_entry { 648194SJack.Meng@Sun.COM int af; 658194SJack.Meng@Sun.COM int e_port; 668194SJack.Meng@Sun.COM char target_name[224]; 678194SJack.Meng@Sun.COM char target_addr[INET6_ADDRSTRLEN]; 688194SJack.Meng@Sun.COM }ibft_entry_t; 698194SJack.Meng@Sun.COM 708194SJack.Meng@Sun.COM typedef struct iSCSI_ibft_tbl_hdr { 718194SJack.Meng@Sun.COM char Signature[4]; 728194SJack.Meng@Sun.COM int Length; 738194SJack.Meng@Sun.COM char Revision; 748194SJack.Meng@Sun.COM char Checksum; 758194SJack.Meng@Sun.COM char oem_id[6]; 768194SJack.Meng@Sun.COM char oem_table_id[8]; 778194SJack.Meng@Sun.COM char Reserved[24]; 788194SJack.Meng@Sun.COM }iscsi_ibft_tbl_hdr_t; 798194SJack.Meng@Sun.COM 808194SJack.Meng@Sun.COM typedef struct iSCSI_ibft_hdr { 818194SJack.Meng@Sun.COM char Structure_id; 828194SJack.Meng@Sun.COM char Version; 838194SJack.Meng@Sun.COM ushort_t Length; 848194SJack.Meng@Sun.COM char Index; 858194SJack.Meng@Sun.COM char Flags; 868194SJack.Meng@Sun.COM }iscsi_ibft_hdr_t; 878194SJack.Meng@Sun.COM 888194SJack.Meng@Sun.COM typedef struct iSCSI_ibft_control { 898194SJack.Meng@Sun.COM iscsi_ibft_hdr_t header; 908194SJack.Meng@Sun.COM ushort_t Extensions; 918194SJack.Meng@Sun.COM ushort_t Initiator_offset; 928194SJack.Meng@Sun.COM ushort_t Nic0_offset; 938194SJack.Meng@Sun.COM ushort_t Target0_offset; 948194SJack.Meng@Sun.COM ushort_t Nic1_offset; 958194SJack.Meng@Sun.COM ushort_t Target1_offset; 968194SJack.Meng@Sun.COM }iscsi_ibft_ctl_t; 978194SJack.Meng@Sun.COM 988194SJack.Meng@Sun.COM typedef struct iSCSI_ibft_initiator { 998194SJack.Meng@Sun.COM iscsi_ibft_hdr_t header; 1008194SJack.Meng@Sun.COM uchar_t iSNS_Server[16]; 1018194SJack.Meng@Sun.COM uchar_t SLP_Server[16]; 1028194SJack.Meng@Sun.COM uchar_t Pri_Radius_Server[16]; 1038194SJack.Meng@Sun.COM uchar_t Sec_Radius_Server[16]; 1048194SJack.Meng@Sun.COM ushort_t ini_name_len; 1058194SJack.Meng@Sun.COM ushort_t ini_name_offset; 1068194SJack.Meng@Sun.COM }iscsi_ibft_initiator_t; 1078194SJack.Meng@Sun.COM 1088194SJack.Meng@Sun.COM typedef struct iSCSI_ibft_nic { 1098194SJack.Meng@Sun.COM iscsi_ibft_hdr_t header; 1108194SJack.Meng@Sun.COM uchar_t ip_addr[16]; 1118194SJack.Meng@Sun.COM char Subnet_Mask_Prefix; 1128194SJack.Meng@Sun.COM char Origin; 1138194SJack.Meng@Sun.COM uchar_t Gateway[16]; 1148194SJack.Meng@Sun.COM uchar_t Primary_dns[16]; 1158194SJack.Meng@Sun.COM uchar_t Secondary_dns[16]; 1168194SJack.Meng@Sun.COM uchar_t dhcp[16]; 1178194SJack.Meng@Sun.COM ushort_t vlan; 1188194SJack.Meng@Sun.COM char mac[6]; 1198194SJack.Meng@Sun.COM ushort_t pci_BDF; 1208194SJack.Meng@Sun.COM ushort_t Hostname_len; 1218194SJack.Meng@Sun.COM ushort_t Hostname_offset; 1228194SJack.Meng@Sun.COM }iscsi_ibft_nic_t; 1238194SJack.Meng@Sun.COM 1248194SJack.Meng@Sun.COM typedef struct iSCSI_ibft_target { 1258194SJack.Meng@Sun.COM iscsi_ibft_hdr_t header; 1268194SJack.Meng@Sun.COM uchar_t ip_addr[16]; 1278194SJack.Meng@Sun.COM ushort_t port; 1288194SJack.Meng@Sun.COM uchar_t boot_lun[8]; 1298194SJack.Meng@Sun.COM uchar_t chap_type; 1308194SJack.Meng@Sun.COM uchar_t nic_association; 1318194SJack.Meng@Sun.COM ushort_t target_name_len; 1328194SJack.Meng@Sun.COM ushort_t target_name_offset; 1338194SJack.Meng@Sun.COM ushort_t chap_name_len; 1348194SJack.Meng@Sun.COM ushort_t chap_name_offset; 1358194SJack.Meng@Sun.COM ushort_t chap_secret_len; 1368194SJack.Meng@Sun.COM ushort_t chap_secret_offset; 1378194SJack.Meng@Sun.COM ushort_t rev_chap_name_len; 1388194SJack.Meng@Sun.COM ushort_t rev_chap_name_offset; 1398194SJack.Meng@Sun.COM ushort_t rev_chap_secret_len; 1408194SJack.Meng@Sun.COM ushort_t rev_chap_secret_offset; 1418194SJack.Meng@Sun.COM }iscsi_ibft_tgt_t; 1428194SJack.Meng@Sun.COM 1438194SJack.Meng@Sun.COM #define ISCSI_IBFT_LOWER_ADDR 0x80000 /* 512K */ 1448194SJack.Meng@Sun.COM #define ISCSI_IBFT_HIGHER_ADDR 0x100000 /* 1024K */ 1458194SJack.Meng@Sun.COM #define ISCSI_IBFT_SIGNATRUE "iBFT" 1468194SJack.Meng@Sun.COM #define ISCSI_IBFT_SIGNATURE_LEN 4 1478194SJack.Meng@Sun.COM #define ISCSI_IBFT_TBL_BUF_LEN 1024 1488194SJack.Meng@Sun.COM #define ISCSI_IBFT_ALIGNED 16 1498194SJack.Meng@Sun.COM #define ISCSI_IBFT_CTL_OFFSET 48 1508194SJack.Meng@Sun.COM 1518194SJack.Meng@Sun.COM #define IBFT_BLOCK_VALID_YES 0x01 /* bit 0 */ 1528194SJack.Meng@Sun.COM #define IBFT_FIRMWARE_BOOT_SELECTED 0x02 /* bit 1 */ 1538194SJack.Meng@Sun.COM #define IBFT_USE_RADIUS_CHAP 0x04 /* bit 2 */ 1548194SJack.Meng@Sun.COM #define IBFT_USE_GLOBLE 0x04 /* NIC structure */ 1558194SJack.Meng@Sun.COM #define IBFT_USE_RADIUS_RHCAP 0x08 /* bit 3 */ 1568194SJack.Meng@Sun.COM 1578194SJack.Meng@Sun.COM /* 1588194SJack.Meng@Sun.COM * Currently, we only support initiator offset, NIC0 offset, Target0 offset, 1598194SJack.Meng@Sun.COM * NIC1 offset and Target1 offset. So the length is 5. If we want to support 1608194SJack.Meng@Sun.COM * extensions, we should change this number. 1618194SJack.Meng@Sun.COM */ 1628194SJack.Meng@Sun.COM #define IBFT_OFFSET_BUF_LEN 5 1638194SJack.Meng@Sun.COM #define IPV4_OFFSET 12 1648194SJack.Meng@Sun.COM 1658194SJack.Meng@Sun.COM #define IBFT_INVALID_MSG "Invalid iBFT table 0x%x" 166*8953SVitezslav.Batrla@Sun.COM #define IBFT_NOPROBE_MSG "iSCSI boot is disabled" 1678194SJack.Meng@Sun.COM 1688194SJack.Meng@Sun.COM typedef enum ibft_status { 1698194SJack.Meng@Sun.COM IBFT_STATUS_OK = 0, 1708194SJack.Meng@Sun.COM /* General error */ 1718194SJack.Meng@Sun.COM IBFT_STATUS_ERR, 1728194SJack.Meng@Sun.COM /* Bad header */ 1738194SJack.Meng@Sun.COM IBFT_STATUS_BADHDR, 1748194SJack.Meng@Sun.COM /* Bad control ID */ 1758194SJack.Meng@Sun.COM IBFT_STATUS_BADCID, 1768194SJack.Meng@Sun.COM /* Bad ip addr */ 1778194SJack.Meng@Sun.COM IBFT_STATUS_BADIP, 1788194SJack.Meng@Sun.COM /* Bad af */ 1798194SJack.Meng@Sun.COM IBFT_STATUS_BADAF, 1808194SJack.Meng@Sun.COM /* Bad chap name */ 1818194SJack.Meng@Sun.COM IBFT_STATUS_BADCHAPNAME, 1828194SJack.Meng@Sun.COM /* Bad chap secret */ 1838194SJack.Meng@Sun.COM IBFT_STATUS_BADCHAPSEC, 1848194SJack.Meng@Sun.COM /* Bad checksum */ 1858194SJack.Meng@Sun.COM IBFT_STATUS_BADCHECKSUM, 1868194SJack.Meng@Sun.COM /* Low memory */ 1878194SJack.Meng@Sun.COM IBFT_STATUS_LOWMEM, 1888194SJack.Meng@Sun.COM /* No table */ 1898194SJack.Meng@Sun.COM IBFT_STATUS_NOTABLE 1908194SJack.Meng@Sun.COM } ibft_status_t; 1918194SJack.Meng@Sun.COM 1928194SJack.Meng@Sun.COM extern void *memset(void *s, int c, size_t n); 1938194SJack.Meng@Sun.COM extern int memcmp(const void *s1, const void *s2, size_t n); 1948194SJack.Meng@Sun.COM extern void bcopy(const void *s1, void *s2, size_t n); 1958194SJack.Meng@Sun.COM extern void iscsi_print_boot_property(); 1968194SJack.Meng@Sun.COM 197*8953SVitezslav.Batrla@Sun.COM int ibft_noprobe = 0; 1988194SJack.Meng@Sun.COM ib_boot_prop_t boot_property; /* static allocated */ 1998194SJack.Meng@Sun.COM extern ib_boot_prop_t *iscsiboot_prop; /* to be filled */ 2008194SJack.Meng@Sun.COM 2018194SJack.Meng@Sun.COM static ibft_status_t iscsi_parse_ibft_control(iscsi_ibft_ctl_t *ctl_hdr, 2028194SJack.Meng@Sun.COM ushort_t *iscsi_offset_buf); 2038194SJack.Meng@Sun.COM 2048194SJack.Meng@Sun.COM static ibft_status_t iscsi_parse_ibft_initiator(char *begin_of_ibft, 2058194SJack.Meng@Sun.COM iscsi_ibft_initiator_t *initiator); 2068194SJack.Meng@Sun.COM 2078194SJack.Meng@Sun.COM static ibft_status_t iscsi_parse_ibft_NIC(iscsi_ibft_nic_t *nicp); 2088194SJack.Meng@Sun.COM 2098194SJack.Meng@Sun.COM static ibft_status_t iscsi_parse_ibft_target(char *begin_of_ibft, 2108194SJack.Meng@Sun.COM iscsi_ibft_tgt_t *tgtp); 2118194SJack.Meng@Sun.COM 2128194SJack.Meng@Sun.COM 2138194SJack.Meng@Sun.COM /* 2148194SJack.Meng@Sun.COM * Return value: 2158194SJack.Meng@Sun.COM * Success: IBFT_STATUS_OK 2168194SJack.Meng@Sun.COM * Fail: IBFT_STATUS_BADCHECKSUM 2178194SJack.Meng@Sun.COM */ 2188194SJack.Meng@Sun.COM static ibft_status_t 2198194SJack.Meng@Sun.COM iscsi_ibft_hdr_checksum(iscsi_ibft_tbl_hdr_t *tbl_hdr) 2208194SJack.Meng@Sun.COM { 2218194SJack.Meng@Sun.COM uchar_t checksum = 0; 2228194SJack.Meng@Sun.COM uchar_t *start = NULL; 2238194SJack.Meng@Sun.COM int length = 0; 2248194SJack.Meng@Sun.COM int i = 0; 2258194SJack.Meng@Sun.COM 2268194SJack.Meng@Sun.COM if (tbl_hdr == NULL) { 2278194SJack.Meng@Sun.COM return (IBFT_STATUS_BADHDR); 2288194SJack.Meng@Sun.COM } 2298194SJack.Meng@Sun.COM 2308194SJack.Meng@Sun.COM length = tbl_hdr->Length; 2318194SJack.Meng@Sun.COM start = (uchar_t *)tbl_hdr; 2328194SJack.Meng@Sun.COM 2338194SJack.Meng@Sun.COM for (i = 0; i < length; i++) { 2348194SJack.Meng@Sun.COM checksum = checksum + start[i]; 2358194SJack.Meng@Sun.COM } 2368194SJack.Meng@Sun.COM 2378194SJack.Meng@Sun.COM if (!checksum) 2388194SJack.Meng@Sun.COM return (IBFT_STATUS_OK); 2398194SJack.Meng@Sun.COM else 2408194SJack.Meng@Sun.COM return (IBFT_STATUS_BADCHECKSUM); 2418194SJack.Meng@Sun.COM } 2428194SJack.Meng@Sun.COM 2438194SJack.Meng@Sun.COM /* 2448194SJack.Meng@Sun.COM * Now we only support one control structure in the IBFT. 2458194SJack.Meng@Sun.COM * So there is no Control ID here. 2468194SJack.Meng@Sun.COM */ 2478194SJack.Meng@Sun.COM static ibft_status_t 2488194SJack.Meng@Sun.COM iscsi_parse_ibft_structure(char *begin_of_ibft, char *buf) 2498194SJack.Meng@Sun.COM { 2508194SJack.Meng@Sun.COM iscsi_ibft_hdr_t *hdr = NULL; 2518194SJack.Meng@Sun.COM ibft_status_t ret = IBFT_STATUS_OK; 2528194SJack.Meng@Sun.COM 2538194SJack.Meng@Sun.COM if (buf == NULL) { 2548194SJack.Meng@Sun.COM return (IBFT_STATUS_ERR); 2558194SJack.Meng@Sun.COM } 2568194SJack.Meng@Sun.COM 2578194SJack.Meng@Sun.COM hdr = (iscsi_ibft_hdr_t *)buf; 2588194SJack.Meng@Sun.COM switch (hdr->Structure_id) { 2598194SJack.Meng@Sun.COM case Initiator: 2608194SJack.Meng@Sun.COM ret = iscsi_parse_ibft_initiator( 2618194SJack.Meng@Sun.COM begin_of_ibft, 2628194SJack.Meng@Sun.COM (iscsi_ibft_initiator_t *)buf); 2638194SJack.Meng@Sun.COM break; 2648194SJack.Meng@Sun.COM case Nic: 2658194SJack.Meng@Sun.COM ret = iscsi_parse_ibft_NIC( 2668194SJack.Meng@Sun.COM (iscsi_ibft_nic_t *)buf); 2678194SJack.Meng@Sun.COM break; 2688194SJack.Meng@Sun.COM case Target: 2698194SJack.Meng@Sun.COM ret = iscsi_parse_ibft_target( 2708194SJack.Meng@Sun.COM begin_of_ibft, 2718194SJack.Meng@Sun.COM (iscsi_ibft_tgt_t *)buf); 2728194SJack.Meng@Sun.COM break; 2738194SJack.Meng@Sun.COM default: 2748194SJack.Meng@Sun.COM ret = IBFT_STATUS_BADHDR; 2758194SJack.Meng@Sun.COM break; 2768194SJack.Meng@Sun.COM } 2778194SJack.Meng@Sun.COM 2788194SJack.Meng@Sun.COM return (ret); 2798194SJack.Meng@Sun.COM } 2808194SJack.Meng@Sun.COM 2818194SJack.Meng@Sun.COM /* 2828194SJack.Meng@Sun.COM * Parse the iBFT table 2838194SJack.Meng@Sun.COM * return IBFT_STATUS_OK upon sucess 2848194SJack.Meng@Sun.COM */ 2858194SJack.Meng@Sun.COM static ibft_status_t 2868194SJack.Meng@Sun.COM iscsi_parse_ibft_tbl(iscsi_ibft_tbl_hdr_t *tbl_hdr) 2878194SJack.Meng@Sun.COM { 2888194SJack.Meng@Sun.COM char *outbuf = NULL; 2898194SJack.Meng@Sun.COM int i = 0; 2908194SJack.Meng@Sun.COM ibft_status_t ret = IBFT_STATUS_OK; 2918194SJack.Meng@Sun.COM ushort_t iscsi_offset_buf[IBFT_OFFSET_BUF_LEN] = {0}; 2928194SJack.Meng@Sun.COM 2938194SJack.Meng@Sun.COM if (tbl_hdr == NULL) { 2948194SJack.Meng@Sun.COM return (IBFT_STATUS_ERR); 2958194SJack.Meng@Sun.COM } 2968194SJack.Meng@Sun.COM 2978194SJack.Meng@Sun.COM if (iscsi_ibft_hdr_checksum(tbl_hdr) != IBFT_STATUS_OK) { 2988194SJack.Meng@Sun.COM return (IBFT_STATUS_BADCHECKSUM); 2998194SJack.Meng@Sun.COM } 3008194SJack.Meng@Sun.COM 3018194SJack.Meng@Sun.COM outbuf = (char *)tbl_hdr; 3028194SJack.Meng@Sun.COM 3038194SJack.Meng@Sun.COM ret = iscsi_parse_ibft_control( 3048194SJack.Meng@Sun.COM (iscsi_ibft_ctl_t *)&outbuf[ISCSI_IBFT_CTL_OFFSET], 3058194SJack.Meng@Sun.COM iscsi_offset_buf); 3068194SJack.Meng@Sun.COM 3078194SJack.Meng@Sun.COM if (ret == IBFT_STATUS_OK) { 3088194SJack.Meng@Sun.COM ret = IBFT_STATUS_ERR; 3098194SJack.Meng@Sun.COM for (i = 0; i < IBFT_OFFSET_BUF_LEN; i++) { 3108194SJack.Meng@Sun.COM if (iscsi_offset_buf[i] != 0) { 3118194SJack.Meng@Sun.COM ret = iscsi_parse_ibft_structure( 3128194SJack.Meng@Sun.COM (char *)tbl_hdr, 3138194SJack.Meng@Sun.COM (char *)tbl_hdr + 3148194SJack.Meng@Sun.COM iscsi_offset_buf[i]); 3158194SJack.Meng@Sun.COM if (ret != IBFT_STATUS_OK) { 3168194SJack.Meng@Sun.COM return (ret); 3178194SJack.Meng@Sun.COM } 3188194SJack.Meng@Sun.COM } 3198194SJack.Meng@Sun.COM } 3208194SJack.Meng@Sun.COM } 3218194SJack.Meng@Sun.COM 3228194SJack.Meng@Sun.COM return (ret); 3238194SJack.Meng@Sun.COM } 3248194SJack.Meng@Sun.COM 3258194SJack.Meng@Sun.COM static ibft_status_t 3268194SJack.Meng@Sun.COM iscsi_parse_ibft_control(iscsi_ibft_ctl_t *ctl_hdr, 3278194SJack.Meng@Sun.COM ushort_t *iscsi_offset_buf) 3288194SJack.Meng@Sun.COM { 3298194SJack.Meng@Sun.COM int i = 0; 3308194SJack.Meng@Sun.COM ushort_t *offsetp = NULL; 3318194SJack.Meng@Sun.COM 3328194SJack.Meng@Sun.COM if (ctl_hdr == NULL) { 3338194SJack.Meng@Sun.COM return (IBFT_STATUS_BADHDR); 3348194SJack.Meng@Sun.COM } 3358194SJack.Meng@Sun.COM 3368194SJack.Meng@Sun.COM if (ctl_hdr->header.Structure_id != Control) { 3378194SJack.Meng@Sun.COM return (IBFT_STATUS_BADCID); 3388194SJack.Meng@Sun.COM } 3398194SJack.Meng@Sun.COM 3408194SJack.Meng@Sun.COM /* 3418194SJack.Meng@Sun.COM * Copy the offsets to offset buffer. 3428194SJack.Meng@Sun.COM */ 3438194SJack.Meng@Sun.COM for (offsetp = &(ctl_hdr->Initiator_offset); i < IBFT_OFFSET_BUF_LEN; 3448194SJack.Meng@Sun.COM offsetp++) { 3458194SJack.Meng@Sun.COM iscsi_offset_buf[i++] = *offsetp; 3468194SJack.Meng@Sun.COM } 3478194SJack.Meng@Sun.COM 3488194SJack.Meng@Sun.COM return (IBFT_STATUS_OK); 3498194SJack.Meng@Sun.COM } 3508194SJack.Meng@Sun.COM 3518194SJack.Meng@Sun.COM /* 3528194SJack.Meng@Sun.COM * We only copy the "Firmare Boot Selseted" and valid initiator 3538194SJack.Meng@Sun.COM * to the boot property. 3548194SJack.Meng@Sun.COM */ 3558194SJack.Meng@Sun.COM static ibft_status_t 3568194SJack.Meng@Sun.COM iscsi_parse_ibft_initiator(char *begin_of_ibft, 3578194SJack.Meng@Sun.COM iscsi_ibft_initiator_t *initiator) 3588194SJack.Meng@Sun.COM { 3598194SJack.Meng@Sun.COM if (initiator == NULL) { 3608194SJack.Meng@Sun.COM return (IBFT_STATUS_ERR); 3618194SJack.Meng@Sun.COM } 3628194SJack.Meng@Sun.COM 3638194SJack.Meng@Sun.COM if (initiator->header.Structure_id != Initiator) { 3648194SJack.Meng@Sun.COM return (IBFT_STATUS_BADHDR); 3658194SJack.Meng@Sun.COM } 3668194SJack.Meng@Sun.COM 3678194SJack.Meng@Sun.COM if ((initiator->header.Flags & IBFT_FIRMWARE_BOOT_SELECTED) && 3688194SJack.Meng@Sun.COM (initiator->header.Flags & IBFT_BLOCK_VALID_YES)) { 3698194SJack.Meng@Sun.COM /* 3708194SJack.Meng@Sun.COM * If the initiator name exists, we will copy it to our own 3718194SJack.Meng@Sun.COM * property structure 3728194SJack.Meng@Sun.COM */ 3738194SJack.Meng@Sun.COM if (initiator->ini_name_len != 0) { 3748194SJack.Meng@Sun.COM boot_property.boot_init.ini_name = 3758194SJack.Meng@Sun.COM (uchar_t *)kmem_zalloc( 3768194SJack.Meng@Sun.COM initiator->ini_name_len + 1, KM_SLEEP); 3778194SJack.Meng@Sun.COM (void) snprintf( 3788194SJack.Meng@Sun.COM (char *)boot_property.boot_init.ini_name, 3798194SJack.Meng@Sun.COM initiator->ini_name_len + 1, "%s", 3808194SJack.Meng@Sun.COM begin_of_ibft + initiator->ini_name_offset); 3818194SJack.Meng@Sun.COM } 3828194SJack.Meng@Sun.COM } 3838194SJack.Meng@Sun.COM return (IBFT_STATUS_OK); 3848194SJack.Meng@Sun.COM } 3858194SJack.Meng@Sun.COM 3868194SJack.Meng@Sun.COM static ibft_status_t 3878194SJack.Meng@Sun.COM iscsi_parse_ipaddr(uchar_t *source, char *dest, int *af) 3888194SJack.Meng@Sun.COM { 3898194SJack.Meng@Sun.COM int i = 0; 3908194SJack.Meng@Sun.COM 3918194SJack.Meng@Sun.COM if (source == NULL) { 3928194SJack.Meng@Sun.COM return (IBFT_STATUS_ERR); 3938194SJack.Meng@Sun.COM } 3948194SJack.Meng@Sun.COM 3958194SJack.Meng@Sun.COM if (source[0] == 0x00 && source[1] == 0x00 && 3968194SJack.Meng@Sun.COM source[2] == 0x00 && source[3] == 0x00 && 3978194SJack.Meng@Sun.COM source[4] == 0x00 && source[5] == 0x00 && 3988194SJack.Meng@Sun.COM source[6] == 0x00 && source[7] == 0x00 && 3998194SJack.Meng@Sun.COM source[8] == 0x00 && source[9] == 0x00 && 4008194SJack.Meng@Sun.COM (source[10] == 0xff) && (source[11] == 0xff)) { 4018194SJack.Meng@Sun.COM /* 4028194SJack.Meng@Sun.COM * IPv4 address 4038194SJack.Meng@Sun.COM */ 4048194SJack.Meng@Sun.COM if (dest != NULL) { 4058194SJack.Meng@Sun.COM (void) sprintf(dest, "%d.%d.%d.%d", 4068194SJack.Meng@Sun.COM source[12], source[13], source[14], source[15]); 4078194SJack.Meng@Sun.COM } 4088194SJack.Meng@Sun.COM if (af != NULL) { 4098194SJack.Meng@Sun.COM *af = AF_INET; 4108194SJack.Meng@Sun.COM } 4118194SJack.Meng@Sun.COM } else { 4128194SJack.Meng@Sun.COM if (dest != NULL) { 4138194SJack.Meng@Sun.COM for (i = 0; i < 14; i = i + 2) { 4148194SJack.Meng@Sun.COM (void) sprintf(dest, "%02x%02x:", source[i], 4158194SJack.Meng@Sun.COM source[i+1]); 4168194SJack.Meng@Sun.COM dest = dest + 5; 4178194SJack.Meng@Sun.COM } 4188194SJack.Meng@Sun.COM (void) sprintf(dest, "%02x%02x", 4198194SJack.Meng@Sun.COM source[i], source[i+1]); 4208194SJack.Meng@Sun.COM } 4218194SJack.Meng@Sun.COM if (af != NULL) { 4228194SJack.Meng@Sun.COM *af = AF_INET6; 4238194SJack.Meng@Sun.COM } 4248194SJack.Meng@Sun.COM } 4258194SJack.Meng@Sun.COM 4268194SJack.Meng@Sun.COM return (IBFT_STATUS_OK); 4278194SJack.Meng@Sun.COM } 4288194SJack.Meng@Sun.COM 4298194SJack.Meng@Sun.COM /* 4308194SJack.Meng@Sun.COM * Copy the ip address from ibft. If IPv4 is used, we should copy 4318194SJack.Meng@Sun.COM * the address from 12th byte. 4328194SJack.Meng@Sun.COM */ 4338194SJack.Meng@Sun.COM static ibft_status_t 4348194SJack.Meng@Sun.COM iscsi_copy_ibft_ipaddr(uchar_t *source, void *dest, int *af) 4358194SJack.Meng@Sun.COM { 4368194SJack.Meng@Sun.COM ibft_status_t ret = IBFT_STATUS_OK; 4378194SJack.Meng@Sun.COM int sin_family = 0; 4388194SJack.Meng@Sun.COM 4398194SJack.Meng@Sun.COM if (source == NULL || dest == NULL) { 4408194SJack.Meng@Sun.COM return (IBFT_STATUS_ERR); 4418194SJack.Meng@Sun.COM } 4428194SJack.Meng@Sun.COM ret = iscsi_parse_ipaddr(source, NULL, &sin_family); 4438194SJack.Meng@Sun.COM if (ret != 0) { 4448194SJack.Meng@Sun.COM return (IBFT_STATUS_BADIP); 4458194SJack.Meng@Sun.COM } 4468194SJack.Meng@Sun.COM 4478194SJack.Meng@Sun.COM if (sin_family == AF_INET) { 4488194SJack.Meng@Sun.COM bcopy(source+IPV4_OFFSET, dest, sizeof (struct in_addr)); 4498194SJack.Meng@Sun.COM } else if (sin_family == AF_INET6) { 4508194SJack.Meng@Sun.COM bcopy(source, dest, sizeof (struct in6_addr)); 4518194SJack.Meng@Sun.COM } else { 4528194SJack.Meng@Sun.COM return (IBFT_STATUS_BADAF); 4538194SJack.Meng@Sun.COM } 4548194SJack.Meng@Sun.COM 4558194SJack.Meng@Sun.COM if (af != NULL) { 4568194SJack.Meng@Sun.COM *af = sin_family; 4578194SJack.Meng@Sun.COM } 4588194SJack.Meng@Sun.COM return (IBFT_STATUS_OK); 4598194SJack.Meng@Sun.COM } 4608194SJack.Meng@Sun.COM 4618194SJack.Meng@Sun.COM /* 4628194SJack.Meng@Sun.COM * Maybe there are multiply NICs are available. We only copy the 4638194SJack.Meng@Sun.COM * "Firmare Boot Selseted" and valid one to the boot property. 4648194SJack.Meng@Sun.COM */ 4658194SJack.Meng@Sun.COM static ibft_status_t 4668194SJack.Meng@Sun.COM iscsi_parse_ibft_NIC(iscsi_ibft_nic_t *nicp) 4678194SJack.Meng@Sun.COM { 4688194SJack.Meng@Sun.COM ibft_status_t ret = IBFT_STATUS_OK; 4698194SJack.Meng@Sun.COM int af = 0; 4708194SJack.Meng@Sun.COM 4718194SJack.Meng@Sun.COM if (nicp == NULL) { 4728194SJack.Meng@Sun.COM return (IBFT_STATUS_ERR); 4738194SJack.Meng@Sun.COM } 4748194SJack.Meng@Sun.COM 4758194SJack.Meng@Sun.COM if (nicp->header.Structure_id != Nic) { 4768194SJack.Meng@Sun.COM return (IBFT_STATUS_ERR); 4778194SJack.Meng@Sun.COM } 4788194SJack.Meng@Sun.COM 4798194SJack.Meng@Sun.COM if ((nicp->header.Flags & IBFT_FIRMWARE_BOOT_SELECTED) && 4808194SJack.Meng@Sun.COM (nicp->header.Flags & IBFT_BLOCK_VALID_YES)) { 4818194SJack.Meng@Sun.COM ret = iscsi_copy_ibft_ipaddr(nicp->ip_addr, 4828194SJack.Meng@Sun.COM &boot_property.boot_nic.nic_ip_u, &af); 4838194SJack.Meng@Sun.COM if (ret != IBFT_STATUS_OK) { 4848194SJack.Meng@Sun.COM return (ret); 4858194SJack.Meng@Sun.COM } 4868194SJack.Meng@Sun.COM 4878194SJack.Meng@Sun.COM boot_property.boot_nic.sin_family = af; 4888194SJack.Meng@Sun.COM 4898194SJack.Meng@Sun.COM ret = iscsi_copy_ibft_ipaddr(nicp->Gateway, 4908194SJack.Meng@Sun.COM &boot_property.boot_nic.nic_gw_u, NULL); 4918194SJack.Meng@Sun.COM if (ret != IBFT_STATUS_OK) { 4928194SJack.Meng@Sun.COM return (ret); 4938194SJack.Meng@Sun.COM } 4948194SJack.Meng@Sun.COM 4958194SJack.Meng@Sun.COM ret = iscsi_copy_ibft_ipaddr(nicp->dhcp, 4968194SJack.Meng@Sun.COM &boot_property.boot_nic.nic_dhcp_u, NULL); 4978194SJack.Meng@Sun.COM if (ret != IBFT_STATUS_OK) { 4988194SJack.Meng@Sun.COM return (ret); 4998194SJack.Meng@Sun.COM } 5008194SJack.Meng@Sun.COM 5018194SJack.Meng@Sun.COM bcopy(nicp->mac, boot_property.boot_nic.nic_mac, 6); 5028194SJack.Meng@Sun.COM boot_property.boot_nic.sub_mask_prefix = 5038194SJack.Meng@Sun.COM nicp->Subnet_Mask_Prefix; 5048194SJack.Meng@Sun.COM } 5058194SJack.Meng@Sun.COM 5068194SJack.Meng@Sun.COM return (IBFT_STATUS_OK); 5078194SJack.Meng@Sun.COM } 5088194SJack.Meng@Sun.COM 5098194SJack.Meng@Sun.COM /* 5108194SJack.Meng@Sun.COM * Maybe there are multiply targets are available. We only copy the 5118194SJack.Meng@Sun.COM * "Firmare Boot Selseted" and valid one to the boot property. 5128194SJack.Meng@Sun.COM */ 5138194SJack.Meng@Sun.COM static ibft_status_t 5148194SJack.Meng@Sun.COM iscsi_parse_ibft_target(char *begin_of_ibft, iscsi_ibft_tgt_t *tgtp) 5158194SJack.Meng@Sun.COM { 5168194SJack.Meng@Sun.COM char *tmp = NULL; 5178194SJack.Meng@Sun.COM int af = 0; 5188194SJack.Meng@Sun.COM ibft_status_t ret = IBFT_STATUS_OK; 5198194SJack.Meng@Sun.COM 5208194SJack.Meng@Sun.COM if (tgtp == NULL) { 5218194SJack.Meng@Sun.COM return (IBFT_STATUS_ERR); 5228194SJack.Meng@Sun.COM } 5238194SJack.Meng@Sun.COM 5248194SJack.Meng@Sun.COM if (tgtp->header.Structure_id != Target) { 5258194SJack.Meng@Sun.COM return (IBFT_STATUS_BADHDR); 5268194SJack.Meng@Sun.COM } 5278194SJack.Meng@Sun.COM 5288194SJack.Meng@Sun.COM if ((tgtp->header.Flags & IBFT_FIRMWARE_BOOT_SELECTED) && 5298194SJack.Meng@Sun.COM (tgtp->header.Flags & IBFT_BLOCK_VALID_YES)) { 5308194SJack.Meng@Sun.COM /* 5318194SJack.Meng@Sun.COM * Get Target Address 5328194SJack.Meng@Sun.COM */ 5338194SJack.Meng@Sun.COM ret = iscsi_copy_ibft_ipaddr(tgtp->ip_addr, 5348194SJack.Meng@Sun.COM &boot_property.boot_tgt.tgt_ip_u, &af); 5358194SJack.Meng@Sun.COM if (ret != IBFT_STATUS_OK) { 5368194SJack.Meng@Sun.COM return (ret); 5378194SJack.Meng@Sun.COM } 5388194SJack.Meng@Sun.COM boot_property.boot_tgt.sin_family = af; 5398194SJack.Meng@Sun.COM /* 5408194SJack.Meng@Sun.COM * Get Target Name 5418194SJack.Meng@Sun.COM */ 5428194SJack.Meng@Sun.COM if (tgtp->target_name_len != 0) { 5438194SJack.Meng@Sun.COM boot_property.boot_tgt.tgt_name = 5448194SJack.Meng@Sun.COM (uchar_t *)kmem_zalloc(tgtp->target_name_len + 1, 5458194SJack.Meng@Sun.COM KM_SLEEP); 5468194SJack.Meng@Sun.COM (void) snprintf( 5478194SJack.Meng@Sun.COM (char *)boot_property.boot_tgt.tgt_name, 5488194SJack.Meng@Sun.COM tgtp->target_name_len + 1, "%s", 5498194SJack.Meng@Sun.COM begin_of_ibft + tgtp->target_name_offset); 5508194SJack.Meng@Sun.COM } else { 5518194SJack.Meng@Sun.COM boot_property.boot_tgt.tgt_name = NULL; 5528194SJack.Meng@Sun.COM } 5538194SJack.Meng@Sun.COM 5548194SJack.Meng@Sun.COM /* Get Dest Port */ 5558194SJack.Meng@Sun.COM boot_property.boot_tgt.tgt_port = tgtp->port; 5568194SJack.Meng@Sun.COM 5578194SJack.Meng@Sun.COM boot_property.boot_tgt.lun_online = 0; 5588194SJack.Meng@Sun.COM 5598194SJack.Meng@Sun.COM /* 5608194SJack.Meng@Sun.COM * Get CHAP secret and name. 5618194SJack.Meng@Sun.COM */ 5628194SJack.Meng@Sun.COM if (tgtp->chap_type != NO_CHAP) { 5638194SJack.Meng@Sun.COM if (tgtp->chap_name_len != 0) { 5648194SJack.Meng@Sun.COM boot_property.boot_init.ini_chap_name = 5658194SJack.Meng@Sun.COM (uchar_t *)kmem_zalloc( 5668194SJack.Meng@Sun.COM tgtp->chap_name_len + 1, 5678194SJack.Meng@Sun.COM KM_SLEEP); 5688194SJack.Meng@Sun.COM tmp = (char *) 5698194SJack.Meng@Sun.COM boot_property.boot_init.ini_chap_name; 5708194SJack.Meng@Sun.COM (void) snprintf( 5718194SJack.Meng@Sun.COM tmp, 5728194SJack.Meng@Sun.COM tgtp->chap_name_len + 1, "%s", 5738194SJack.Meng@Sun.COM begin_of_ibft + tgtp->chap_name_offset); 5748194SJack.Meng@Sun.COM } else { 5758194SJack.Meng@Sun.COM /* 5768194SJack.Meng@Sun.COM * Just set NULL, initiator is able to deal 5778194SJack.Meng@Sun.COM * with this 5788194SJack.Meng@Sun.COM */ 5798194SJack.Meng@Sun.COM boot_property.boot_init.ini_chap_name = NULL; 5808194SJack.Meng@Sun.COM } 5818194SJack.Meng@Sun.COM 5828194SJack.Meng@Sun.COM if (tgtp->chap_secret_len != 0) { 5838194SJack.Meng@Sun.COM boot_property.boot_init.ini_chap_sec = 5848194SJack.Meng@Sun.COM (uchar_t *)kmem_zalloc( 5858194SJack.Meng@Sun.COM tgtp->chap_secret_len + 1, 5868194SJack.Meng@Sun.COM KM_SLEEP); 5878194SJack.Meng@Sun.COM bcopy(begin_of_ibft + 5888194SJack.Meng@Sun.COM tgtp->chap_secret_offset, 5898194SJack.Meng@Sun.COM boot_property.boot_init.ini_chap_sec, 5908194SJack.Meng@Sun.COM tgtp->chap_secret_len); 5918194SJack.Meng@Sun.COM } else { 5928194SJack.Meng@Sun.COM boot_property.boot_init.ini_chap_sec = NULL; 5938194SJack.Meng@Sun.COM return (IBFT_STATUS_ERR); 5948194SJack.Meng@Sun.COM } 5958194SJack.Meng@Sun.COM 5968194SJack.Meng@Sun.COM if (tgtp->chap_type == Mutual_CHAP) { 5978194SJack.Meng@Sun.COM if (tgtp->rev_chap_name_len != 0) { 5988194SJack.Meng@Sun.COM boot_property.boot_tgt.tgt_chap_name = 5998194SJack.Meng@Sun.COM (uchar_t *)kmem_zalloc( 6008194SJack.Meng@Sun.COM tgtp->chap_name_len + 1, 6018194SJack.Meng@Sun.COM KM_SLEEP); 6028194SJack.Meng@Sun.COM #define TGT_CHAP_NAME boot_property.boot_tgt.tgt_chap_name 6038194SJack.Meng@Sun.COM tmp = (char *)TGT_CHAP_NAME; 6048194SJack.Meng@Sun.COM #undef TGT_CHAP_NAME 6058194SJack.Meng@Sun.COM (void) snprintf( 6068194SJack.Meng@Sun.COM tmp, 6078194SJack.Meng@Sun.COM tgtp->chap_name_len + 1, 6088194SJack.Meng@Sun.COM "%s", 6098194SJack.Meng@Sun.COM begin_of_ibft + 6108194SJack.Meng@Sun.COM tgtp->rev_chap_name_offset); 6118194SJack.Meng@Sun.COM } else { 6128194SJack.Meng@Sun.COM /* 6138194SJack.Meng@Sun.COM * Just set NULL, initiator is able 6148194SJack.Meng@Sun.COM * to deal with this 6158194SJack.Meng@Sun.COM */ 6168194SJack.Meng@Sun.COM boot_property.boot_tgt.tgt_chap_name = 6178194SJack.Meng@Sun.COM NULL; 6188194SJack.Meng@Sun.COM } 6198194SJack.Meng@Sun.COM 6208194SJack.Meng@Sun.COM if (tgtp->rev_chap_secret_len != 0) { 6218194SJack.Meng@Sun.COM boot_property.boot_tgt.tgt_chap_sec = 6228194SJack.Meng@Sun.COM (uchar_t *)kmem_zalloc( 6238194SJack.Meng@Sun.COM tgtp->rev_chap_secret_len + 1, 6248194SJack.Meng@Sun.COM KM_SLEEP); 6258194SJack.Meng@Sun.COM tmp = (char *) 6268194SJack.Meng@Sun.COM boot_property.boot_tgt.tgt_chap_sec; 6278194SJack.Meng@Sun.COM (void) snprintf( 6288194SJack.Meng@Sun.COM tmp, 6298194SJack.Meng@Sun.COM tgtp->rev_chap_secret_len + 1, 6308194SJack.Meng@Sun.COM "%s", 6318194SJack.Meng@Sun.COM begin_of_ibft + 6328194SJack.Meng@Sun.COM tgtp->chap_secret_offset); 6338194SJack.Meng@Sun.COM } else { 6348194SJack.Meng@Sun.COM boot_property.boot_tgt.tgt_chap_sec = 6358194SJack.Meng@Sun.COM NULL; 6368194SJack.Meng@Sun.COM return (IBFT_STATUS_BADCHAPSEC); 6378194SJack.Meng@Sun.COM } 6388194SJack.Meng@Sun.COM } 6398194SJack.Meng@Sun.COM } else { 6408194SJack.Meng@Sun.COM boot_property.boot_init.ini_chap_name = NULL; 6418194SJack.Meng@Sun.COM boot_property.boot_init.ini_chap_sec = NULL; 6428194SJack.Meng@Sun.COM } 6438194SJack.Meng@Sun.COM 6448194SJack.Meng@Sun.COM /* 6458194SJack.Meng@Sun.COM * Get Boot LUN 6468194SJack.Meng@Sun.COM */ 6478194SJack.Meng@Sun.COM (void) bcopy(tgtp->boot_lun, 6488194SJack.Meng@Sun.COM boot_property.boot_tgt.tgt_boot_lun, 8); 6498194SJack.Meng@Sun.COM } 6508194SJack.Meng@Sun.COM 6518194SJack.Meng@Sun.COM return (IBFT_STATUS_OK); 6528194SJack.Meng@Sun.COM } 6538194SJack.Meng@Sun.COM 6548194SJack.Meng@Sun.COM /* 6558194SJack.Meng@Sun.COM * This function is used for scanning iBFT from the physical memory. 6568194SJack.Meng@Sun.COM * Return Value: 6578194SJack.Meng@Sun.COM * IBFT_STATUS_OK 6588194SJack.Meng@Sun.COM * IBFT_STATUS_ERR 6598194SJack.Meng@Sun.COM */ 6608194SJack.Meng@Sun.COM static ibft_status_t 6618194SJack.Meng@Sun.COM iscsi_scan_ibft_tbl(char *ibft_tbl_buf) 6628194SJack.Meng@Sun.COM { 6638194SJack.Meng@Sun.COM int start; 6648194SJack.Meng@Sun.COM void *va = NULL; 6658194SJack.Meng@Sun.COM int *len = NULL; 6668194SJack.Meng@Sun.COM ibft_status_t ret = IBFT_STATUS_NOTABLE; 6678194SJack.Meng@Sun.COM 6688194SJack.Meng@Sun.COM for (start = ISCSI_IBFT_LOWER_ADDR; start < ISCSI_IBFT_HIGHER_ADDR; 6698194SJack.Meng@Sun.COM start = start + ISCSI_IBFT_ALIGNED) { 6708194SJack.Meng@Sun.COM va = (void *)psm_map((paddr_t)(start&0xffffffff), 6718194SJack.Meng@Sun.COM ISCSI_IBFT_SIGNATURE_LEN, 6728194SJack.Meng@Sun.COM PROT_READ); 6738194SJack.Meng@Sun.COM 6748194SJack.Meng@Sun.COM if (va == NULL) { 6758194SJack.Meng@Sun.COM continue; 6768194SJack.Meng@Sun.COM } 6778194SJack.Meng@Sun.COM if (memcmp(va, ISCSI_IBFT_SIGNATRUE, 6788194SJack.Meng@Sun.COM ISCSI_IBFT_SIGNATURE_LEN) == 0) { 6798194SJack.Meng@Sun.COM ret = IBFT_STATUS_ERR; 6808194SJack.Meng@Sun.COM /* Acquire table length */ 6818194SJack.Meng@Sun.COM len = (int *)psm_map( 6828194SJack.Meng@Sun.COM (paddr_t)((start+\ 6838194SJack.Meng@Sun.COM ISCSI_IBFT_SIGNATURE_LEN)&0xffffffff), 6848194SJack.Meng@Sun.COM ISCSI_IBFT_SIGNATURE_LEN, PROT_READ); 6858194SJack.Meng@Sun.COM if (len == NULL) { 6868194SJack.Meng@Sun.COM psm_unmap((caddr_t)va, 6878194SJack.Meng@Sun.COM ISCSI_IBFT_SIGNATURE_LEN); 6888194SJack.Meng@Sun.COM continue; 6898194SJack.Meng@Sun.COM } 6908194SJack.Meng@Sun.COM if (ISCSI_IBFT_LOWER_ADDR + *len < 6918194SJack.Meng@Sun.COM ISCSI_IBFT_HIGHER_ADDR - 1) { 6928194SJack.Meng@Sun.COM psm_unmap(va, 6938194SJack.Meng@Sun.COM ISCSI_IBFT_SIGNATURE_LEN); 6948194SJack.Meng@Sun.COM va = psm_map((paddr_t)(start&0xffffffff), 6958194SJack.Meng@Sun.COM *len, 6968194SJack.Meng@Sun.COM PROT_READ); 6978194SJack.Meng@Sun.COM if (va != NULL) { 6988194SJack.Meng@Sun.COM /* 6998194SJack.Meng@Sun.COM * Copy data to our own buffer 7008194SJack.Meng@Sun.COM */ 7018194SJack.Meng@Sun.COM bcopy(va, ibft_tbl_buf, *len); 7028194SJack.Meng@Sun.COM ret = IBFT_STATUS_OK; 7038194SJack.Meng@Sun.COM } 7048194SJack.Meng@Sun.COM psm_unmap((caddr_t)va, *len); 7058194SJack.Meng@Sun.COM psm_unmap((caddr_t)len, 7068194SJack.Meng@Sun.COM ISCSI_IBFT_SIGNATURE_LEN); 7078194SJack.Meng@Sun.COM break; 7088194SJack.Meng@Sun.COM } else { 7098194SJack.Meng@Sun.COM psm_unmap((caddr_t)va, 7108194SJack.Meng@Sun.COM ISCSI_IBFT_SIGNATURE_LEN); 7118194SJack.Meng@Sun.COM psm_unmap((caddr_t)len, 7128194SJack.Meng@Sun.COM ISCSI_IBFT_SIGNATURE_LEN); 7138194SJack.Meng@Sun.COM } 7148194SJack.Meng@Sun.COM } else { 7158194SJack.Meng@Sun.COM psm_unmap((caddr_t)va, ISCSI_IBFT_SIGNATURE_LEN); 7168194SJack.Meng@Sun.COM } 7178194SJack.Meng@Sun.COM } 7188194SJack.Meng@Sun.COM 7198194SJack.Meng@Sun.COM return (ret); 7208194SJack.Meng@Sun.COM } 7218194SJack.Meng@Sun.COM 7228194SJack.Meng@Sun.COM /* 7238194SJack.Meng@Sun.COM * Scan the ibft table and store the iSCSI boot properties 7248194SJack.Meng@Sun.COM * If there is a valid table then set the iscsiboot_prop 7258194SJack.Meng@Sun.COM * iBF should be off if the host is not intended 7268194SJack.Meng@Sun.COM * to be booted from iSCSI disk 7278194SJack.Meng@Sun.COM */ 7288194SJack.Meng@Sun.COM void 7298194SJack.Meng@Sun.COM ld_ib_prop() 7308194SJack.Meng@Sun.COM { 7318194SJack.Meng@Sun.COM ibft_status_t ret = IBFT_STATUS_OK; 7328194SJack.Meng@Sun.COM char *ibft_tbl_buf; 7338194SJack.Meng@Sun.COM 734*8953SVitezslav.Batrla@Sun.COM if (do_bsys_getproplen(NULL, "ibft-noprobe") > 0) 735*8953SVitezslav.Batrla@Sun.COM ibft_noprobe = 1; 736*8953SVitezslav.Batrla@Sun.COM 737*8953SVitezslav.Batrla@Sun.COM if (ibft_noprobe != 0) { 738*8953SVitezslav.Batrla@Sun.COM /* 739*8953SVitezslav.Batrla@Sun.COM * Scanning for iBFT may conflict with devices which use memory 740*8953SVitezslav.Batrla@Sun.COM * in 640-1024KB of physical address space. The iBFT 741*8953SVitezslav.Batrla@Sun.COM * specification suggests use of low RAM method - scanning 742*8953SVitezslav.Batrla@Sun.COM * physical memory 512-1024 KB for iBFT table. However, the 743*8953SVitezslav.Batrla@Sun.COM * Upper Memory Area (UMA) 640-1024 KB may contain device 744*8953SVitezslav.Batrla@Sun.COM * memory or memory mapped I/O. Although reading from I/O area 745*8953SVitezslav.Batrla@Sun.COM * is usually fine, the actual behavior depends on device 746*8953SVitezslav.Batrla@Sun.COM * implementation. In some cases, the user may want to disable 747*8953SVitezslav.Batrla@Sun.COM * low RAM method and prevent reading from device I/O area. 748*8953SVitezslav.Batrla@Sun.COM * 749*8953SVitezslav.Batrla@Sun.COM * To disable low RAM method: 750*8953SVitezslav.Batrla@Sun.COM * 1) pass "-B ibft-noprobe=1" on kernel command line 751*8953SVitezslav.Batrla@Sun.COM * 2) add line "set ibft_noprobe=1" in /etc/system 752*8953SVitezslav.Batrla@Sun.COM */ 753*8953SVitezslav.Batrla@Sun.COM cmn_err(CE_NOTE, IBFT_NOPROBE_MSG); 754*8953SVitezslav.Batrla@Sun.COM return; 755*8953SVitezslav.Batrla@Sun.COM } 756*8953SVitezslav.Batrla@Sun.COM 7578194SJack.Meng@Sun.COM ibft_tbl_buf = (char *)kmem_zalloc(ISCSI_IBFT_TBL_BUF_LEN, 7588194SJack.Meng@Sun.COM KM_SLEEP); 7598194SJack.Meng@Sun.COM 7608194SJack.Meng@Sun.COM if (!ibft_tbl_buf) { 7618194SJack.Meng@Sun.COM /* Unlikely to happen */ 7628194SJack.Meng@Sun.COM cmn_err(CE_NOTE, IBFT_INVALID_MSG, 7638194SJack.Meng@Sun.COM IBFT_STATUS_LOWMEM); 7648194SJack.Meng@Sun.COM return; 7658194SJack.Meng@Sun.COM } 7668194SJack.Meng@Sun.COM 7678194SJack.Meng@Sun.COM (void) memset(&boot_property, 0, sizeof (boot_property)); 7688194SJack.Meng@Sun.COM if ((ret = iscsi_scan_ibft_tbl(ibft_tbl_buf)) == 7698194SJack.Meng@Sun.COM IBFT_STATUS_OK) { 7708194SJack.Meng@Sun.COM ret = iscsi_parse_ibft_tbl( 7718194SJack.Meng@Sun.COM (iscsi_ibft_tbl_hdr_t *)ibft_tbl_buf); 7728194SJack.Meng@Sun.COM if (ret == IBFT_STATUS_OK) { 7738194SJack.Meng@Sun.COM iscsiboot_prop = &boot_property; 7748194SJack.Meng@Sun.COM iscsi_print_boot_property(); 7758194SJack.Meng@Sun.COM } else { 7768194SJack.Meng@Sun.COM cmn_err(CE_NOTE, IBFT_INVALID_MSG, ret); 7778194SJack.Meng@Sun.COM } 7788194SJack.Meng@Sun.COM } else if (ret != IBFT_STATUS_NOTABLE) { 7798194SJack.Meng@Sun.COM cmn_err(CE_NOTE, IBFT_INVALID_MSG, ret); 7808194SJack.Meng@Sun.COM } 7818194SJack.Meng@Sun.COM 7828194SJack.Meng@Sun.COM kmem_free(ibft_tbl_buf, ISCSI_IBFT_TBL_BUF_LEN); 7838194SJack.Meng@Sun.COM } 784