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 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 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 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 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 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 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 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 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 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 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 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