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 /*
238953SVitezslav.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>
408953SVitezslav.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"
1668953SVitezslav.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
1978953SVitezslav.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
iscsi_ibft_hdr_checksum(iscsi_ibft_tbl_hdr_t * tbl_hdr)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
iscsi_parse_ibft_structure(char * begin_of_ibft,char * buf)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
iscsi_parse_ibft_tbl(iscsi_ibft_tbl_hdr_t * tbl_hdr)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
iscsi_parse_ibft_control(iscsi_ibft_ctl_t * ctl_hdr,ushort_t * iscsi_offset_buf)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
iscsi_parse_ibft_initiator(char * begin_of_ibft,iscsi_ibft_initiator_t * initiator)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);
377*10822SJack.Meng@Sun.COM boot_property.boot_init.ini_name_len =
378*10822SJack.Meng@Sun.COM initiator->ini_name_len + 1;
3798194SJack.Meng@Sun.COM (void) snprintf(
3808194SJack.Meng@Sun.COM (char *)boot_property.boot_init.ini_name,
3818194SJack.Meng@Sun.COM initiator->ini_name_len + 1, "%s",
3828194SJack.Meng@Sun.COM begin_of_ibft + initiator->ini_name_offset);
3838194SJack.Meng@Sun.COM }
3848194SJack.Meng@Sun.COM }
3858194SJack.Meng@Sun.COM return (IBFT_STATUS_OK);
3868194SJack.Meng@Sun.COM }
3878194SJack.Meng@Sun.COM
3888194SJack.Meng@Sun.COM static ibft_status_t
iscsi_parse_ipaddr(uchar_t * source,char * dest,int * af)3898194SJack.Meng@Sun.COM iscsi_parse_ipaddr(uchar_t *source, char *dest, int *af)
3908194SJack.Meng@Sun.COM {
3918194SJack.Meng@Sun.COM int i = 0;
3928194SJack.Meng@Sun.COM
3938194SJack.Meng@Sun.COM if (source == NULL) {
3948194SJack.Meng@Sun.COM return (IBFT_STATUS_ERR);
3958194SJack.Meng@Sun.COM }
3968194SJack.Meng@Sun.COM
3978194SJack.Meng@Sun.COM if (source[0] == 0x00 && source[1] == 0x00 &&
3988194SJack.Meng@Sun.COM source[2] == 0x00 && source[3] == 0x00 &&
3998194SJack.Meng@Sun.COM source[4] == 0x00 && source[5] == 0x00 &&
4008194SJack.Meng@Sun.COM source[6] == 0x00 && source[7] == 0x00 &&
4018194SJack.Meng@Sun.COM source[8] == 0x00 && source[9] == 0x00 &&
4028194SJack.Meng@Sun.COM (source[10] == 0xff) && (source[11] == 0xff)) {
4038194SJack.Meng@Sun.COM /*
4048194SJack.Meng@Sun.COM * IPv4 address
4058194SJack.Meng@Sun.COM */
4068194SJack.Meng@Sun.COM if (dest != NULL) {
4078194SJack.Meng@Sun.COM (void) sprintf(dest, "%d.%d.%d.%d",
4088194SJack.Meng@Sun.COM source[12], source[13], source[14], source[15]);
4098194SJack.Meng@Sun.COM }
4108194SJack.Meng@Sun.COM if (af != NULL) {
4118194SJack.Meng@Sun.COM *af = AF_INET;
4128194SJack.Meng@Sun.COM }
4138194SJack.Meng@Sun.COM } else {
4148194SJack.Meng@Sun.COM if (dest != NULL) {
4158194SJack.Meng@Sun.COM for (i = 0; i < 14; i = i + 2) {
4168194SJack.Meng@Sun.COM (void) sprintf(dest, "%02x%02x:", source[i],
4178194SJack.Meng@Sun.COM source[i+1]);
4188194SJack.Meng@Sun.COM dest = dest + 5;
4198194SJack.Meng@Sun.COM }
4208194SJack.Meng@Sun.COM (void) sprintf(dest, "%02x%02x",
4218194SJack.Meng@Sun.COM source[i], source[i+1]);
4228194SJack.Meng@Sun.COM }
4238194SJack.Meng@Sun.COM if (af != NULL) {
4248194SJack.Meng@Sun.COM *af = AF_INET6;
4258194SJack.Meng@Sun.COM }
4268194SJack.Meng@Sun.COM }
4278194SJack.Meng@Sun.COM
4288194SJack.Meng@Sun.COM return (IBFT_STATUS_OK);
4298194SJack.Meng@Sun.COM }
4308194SJack.Meng@Sun.COM
4318194SJack.Meng@Sun.COM /*
4328194SJack.Meng@Sun.COM * Copy the ip address from ibft. If IPv4 is used, we should copy
4338194SJack.Meng@Sun.COM * the address from 12th byte.
4348194SJack.Meng@Sun.COM */
4358194SJack.Meng@Sun.COM static ibft_status_t
iscsi_copy_ibft_ipaddr(uchar_t * source,void * dest,int * af)4368194SJack.Meng@Sun.COM iscsi_copy_ibft_ipaddr(uchar_t *source, void *dest, int *af)
4378194SJack.Meng@Sun.COM {
4388194SJack.Meng@Sun.COM ibft_status_t ret = IBFT_STATUS_OK;
4398194SJack.Meng@Sun.COM int sin_family = 0;
4408194SJack.Meng@Sun.COM
4418194SJack.Meng@Sun.COM if (source == NULL || dest == NULL) {
4428194SJack.Meng@Sun.COM return (IBFT_STATUS_ERR);
4438194SJack.Meng@Sun.COM }
4448194SJack.Meng@Sun.COM ret = iscsi_parse_ipaddr(source, NULL, &sin_family);
4458194SJack.Meng@Sun.COM if (ret != 0) {
4468194SJack.Meng@Sun.COM return (IBFT_STATUS_BADIP);
4478194SJack.Meng@Sun.COM }
4488194SJack.Meng@Sun.COM
4498194SJack.Meng@Sun.COM if (sin_family == AF_INET) {
4508194SJack.Meng@Sun.COM bcopy(source+IPV4_OFFSET, dest, sizeof (struct in_addr));
4518194SJack.Meng@Sun.COM } else if (sin_family == AF_INET6) {
4528194SJack.Meng@Sun.COM bcopy(source, dest, sizeof (struct in6_addr));
4538194SJack.Meng@Sun.COM } else {
4548194SJack.Meng@Sun.COM return (IBFT_STATUS_BADAF);
4558194SJack.Meng@Sun.COM }
4568194SJack.Meng@Sun.COM
4578194SJack.Meng@Sun.COM if (af != NULL) {
4588194SJack.Meng@Sun.COM *af = sin_family;
4598194SJack.Meng@Sun.COM }
4608194SJack.Meng@Sun.COM return (IBFT_STATUS_OK);
4618194SJack.Meng@Sun.COM }
4628194SJack.Meng@Sun.COM
4638194SJack.Meng@Sun.COM /*
4648194SJack.Meng@Sun.COM * Maybe there are multiply NICs are available. We only copy the
4658194SJack.Meng@Sun.COM * "Firmare Boot Selseted" and valid one to the boot property.
4668194SJack.Meng@Sun.COM */
4678194SJack.Meng@Sun.COM static ibft_status_t
iscsi_parse_ibft_NIC(iscsi_ibft_nic_t * nicp)4688194SJack.Meng@Sun.COM iscsi_parse_ibft_NIC(iscsi_ibft_nic_t *nicp)
4698194SJack.Meng@Sun.COM {
4708194SJack.Meng@Sun.COM ibft_status_t ret = IBFT_STATUS_OK;
4718194SJack.Meng@Sun.COM int af = 0;
4728194SJack.Meng@Sun.COM
4738194SJack.Meng@Sun.COM if (nicp == NULL) {
4748194SJack.Meng@Sun.COM return (IBFT_STATUS_ERR);
4758194SJack.Meng@Sun.COM }
4768194SJack.Meng@Sun.COM
4778194SJack.Meng@Sun.COM if (nicp->header.Structure_id != Nic) {
4788194SJack.Meng@Sun.COM return (IBFT_STATUS_ERR);
4798194SJack.Meng@Sun.COM }
4808194SJack.Meng@Sun.COM
4818194SJack.Meng@Sun.COM if ((nicp->header.Flags & IBFT_FIRMWARE_BOOT_SELECTED) &&
4828194SJack.Meng@Sun.COM (nicp->header.Flags & IBFT_BLOCK_VALID_YES)) {
4838194SJack.Meng@Sun.COM ret = iscsi_copy_ibft_ipaddr(nicp->ip_addr,
4848194SJack.Meng@Sun.COM &boot_property.boot_nic.nic_ip_u, &af);
4858194SJack.Meng@Sun.COM if (ret != IBFT_STATUS_OK) {
4868194SJack.Meng@Sun.COM return (ret);
4878194SJack.Meng@Sun.COM }
4888194SJack.Meng@Sun.COM
4898194SJack.Meng@Sun.COM boot_property.boot_nic.sin_family = af;
4908194SJack.Meng@Sun.COM
4918194SJack.Meng@Sun.COM ret = iscsi_copy_ibft_ipaddr(nicp->Gateway,
4928194SJack.Meng@Sun.COM &boot_property.boot_nic.nic_gw_u, NULL);
4938194SJack.Meng@Sun.COM if (ret != IBFT_STATUS_OK) {
4948194SJack.Meng@Sun.COM return (ret);
4958194SJack.Meng@Sun.COM }
4968194SJack.Meng@Sun.COM
4978194SJack.Meng@Sun.COM ret = iscsi_copy_ibft_ipaddr(nicp->dhcp,
4988194SJack.Meng@Sun.COM &boot_property.boot_nic.nic_dhcp_u, NULL);
4998194SJack.Meng@Sun.COM if (ret != IBFT_STATUS_OK) {
5008194SJack.Meng@Sun.COM return (ret);
5018194SJack.Meng@Sun.COM }
5028194SJack.Meng@Sun.COM
5038194SJack.Meng@Sun.COM bcopy(nicp->mac, boot_property.boot_nic.nic_mac, 6);
5048194SJack.Meng@Sun.COM boot_property.boot_nic.sub_mask_prefix =
5058194SJack.Meng@Sun.COM nicp->Subnet_Mask_Prefix;
5068194SJack.Meng@Sun.COM }
5078194SJack.Meng@Sun.COM
5088194SJack.Meng@Sun.COM return (IBFT_STATUS_OK);
5098194SJack.Meng@Sun.COM }
5108194SJack.Meng@Sun.COM
5118194SJack.Meng@Sun.COM /*
5128194SJack.Meng@Sun.COM * Maybe there are multiply targets are available. We only copy the
5138194SJack.Meng@Sun.COM * "Firmare Boot Selseted" and valid one to the boot property.
5148194SJack.Meng@Sun.COM */
5158194SJack.Meng@Sun.COM static ibft_status_t
iscsi_parse_ibft_target(char * begin_of_ibft,iscsi_ibft_tgt_t * tgtp)5168194SJack.Meng@Sun.COM iscsi_parse_ibft_target(char *begin_of_ibft, iscsi_ibft_tgt_t *tgtp)
5178194SJack.Meng@Sun.COM {
5188194SJack.Meng@Sun.COM char *tmp = NULL;
5198194SJack.Meng@Sun.COM int af = 0;
5208194SJack.Meng@Sun.COM ibft_status_t ret = IBFT_STATUS_OK;
5218194SJack.Meng@Sun.COM
5228194SJack.Meng@Sun.COM if (tgtp == NULL) {
5238194SJack.Meng@Sun.COM return (IBFT_STATUS_ERR);
5248194SJack.Meng@Sun.COM }
5258194SJack.Meng@Sun.COM
5268194SJack.Meng@Sun.COM if (tgtp->header.Structure_id != Target) {
5278194SJack.Meng@Sun.COM return (IBFT_STATUS_BADHDR);
5288194SJack.Meng@Sun.COM }
5298194SJack.Meng@Sun.COM
5308194SJack.Meng@Sun.COM if ((tgtp->header.Flags & IBFT_FIRMWARE_BOOT_SELECTED) &&
5318194SJack.Meng@Sun.COM (tgtp->header.Flags & IBFT_BLOCK_VALID_YES)) {
5328194SJack.Meng@Sun.COM /*
5338194SJack.Meng@Sun.COM * Get Target Address
5348194SJack.Meng@Sun.COM */
5358194SJack.Meng@Sun.COM ret = iscsi_copy_ibft_ipaddr(tgtp->ip_addr,
5368194SJack.Meng@Sun.COM &boot_property.boot_tgt.tgt_ip_u, &af);
5378194SJack.Meng@Sun.COM if (ret != IBFT_STATUS_OK) {
5388194SJack.Meng@Sun.COM return (ret);
5398194SJack.Meng@Sun.COM }
5408194SJack.Meng@Sun.COM boot_property.boot_tgt.sin_family = af;
5418194SJack.Meng@Sun.COM /*
5428194SJack.Meng@Sun.COM * Get Target Name
5438194SJack.Meng@Sun.COM */
5448194SJack.Meng@Sun.COM if (tgtp->target_name_len != 0) {
5458194SJack.Meng@Sun.COM boot_property.boot_tgt.tgt_name =
5468194SJack.Meng@Sun.COM (uchar_t *)kmem_zalloc(tgtp->target_name_len + 1,
5478194SJack.Meng@Sun.COM KM_SLEEP);
548*10822SJack.Meng@Sun.COM boot_property.boot_tgt.tgt_name_len =
549*10822SJack.Meng@Sun.COM tgtp->target_name_len + 1;
5508194SJack.Meng@Sun.COM (void) snprintf(
5518194SJack.Meng@Sun.COM (char *)boot_property.boot_tgt.tgt_name,
5528194SJack.Meng@Sun.COM tgtp->target_name_len + 1, "%s",
5538194SJack.Meng@Sun.COM begin_of_ibft + tgtp->target_name_offset);
5548194SJack.Meng@Sun.COM } else {
5558194SJack.Meng@Sun.COM boot_property.boot_tgt.tgt_name = NULL;
5568194SJack.Meng@Sun.COM }
5578194SJack.Meng@Sun.COM
5588194SJack.Meng@Sun.COM /* Get Dest Port */
5598194SJack.Meng@Sun.COM boot_property.boot_tgt.tgt_port = tgtp->port;
5608194SJack.Meng@Sun.COM
5618194SJack.Meng@Sun.COM boot_property.boot_tgt.lun_online = 0;
5628194SJack.Meng@Sun.COM
5638194SJack.Meng@Sun.COM /*
5648194SJack.Meng@Sun.COM * Get CHAP secret and name.
5658194SJack.Meng@Sun.COM */
5668194SJack.Meng@Sun.COM if (tgtp->chap_type != NO_CHAP) {
5678194SJack.Meng@Sun.COM if (tgtp->chap_name_len != 0) {
5688194SJack.Meng@Sun.COM boot_property.boot_init.ini_chap_name =
5698194SJack.Meng@Sun.COM (uchar_t *)kmem_zalloc(
5708194SJack.Meng@Sun.COM tgtp->chap_name_len + 1,
5718194SJack.Meng@Sun.COM KM_SLEEP);
572*10822SJack.Meng@Sun.COM boot_property.boot_init.ini_chap_name_len =
573*10822SJack.Meng@Sun.COM tgtp->chap_name_len + 1;
5748194SJack.Meng@Sun.COM tmp = (char *)
5758194SJack.Meng@Sun.COM boot_property.boot_init.ini_chap_name;
5768194SJack.Meng@Sun.COM (void) snprintf(
5778194SJack.Meng@Sun.COM tmp,
5788194SJack.Meng@Sun.COM tgtp->chap_name_len + 1, "%s",
5798194SJack.Meng@Sun.COM begin_of_ibft + tgtp->chap_name_offset);
5808194SJack.Meng@Sun.COM } else {
5818194SJack.Meng@Sun.COM /*
5828194SJack.Meng@Sun.COM * Just set NULL, initiator is able to deal
5838194SJack.Meng@Sun.COM * with this
5848194SJack.Meng@Sun.COM */
5858194SJack.Meng@Sun.COM boot_property.boot_init.ini_chap_name = NULL;
5868194SJack.Meng@Sun.COM }
5878194SJack.Meng@Sun.COM
5888194SJack.Meng@Sun.COM if (tgtp->chap_secret_len != 0) {
5898194SJack.Meng@Sun.COM boot_property.boot_init.ini_chap_sec =
5908194SJack.Meng@Sun.COM (uchar_t *)kmem_zalloc(
5918194SJack.Meng@Sun.COM tgtp->chap_secret_len + 1,
5928194SJack.Meng@Sun.COM KM_SLEEP);
593*10822SJack.Meng@Sun.COM boot_property.boot_init.ini_chap_sec_len =
594*10822SJack.Meng@Sun.COM tgtp->chap_secret_len + 1;
5958194SJack.Meng@Sun.COM bcopy(begin_of_ibft +
5968194SJack.Meng@Sun.COM tgtp->chap_secret_offset,
5978194SJack.Meng@Sun.COM boot_property.boot_init.ini_chap_sec,
5988194SJack.Meng@Sun.COM tgtp->chap_secret_len);
5998194SJack.Meng@Sun.COM } else {
6008194SJack.Meng@Sun.COM boot_property.boot_init.ini_chap_sec = NULL;
6018194SJack.Meng@Sun.COM return (IBFT_STATUS_ERR);
6028194SJack.Meng@Sun.COM }
6038194SJack.Meng@Sun.COM
6048194SJack.Meng@Sun.COM if (tgtp->chap_type == Mutual_CHAP) {
6058194SJack.Meng@Sun.COM if (tgtp->rev_chap_name_len != 0) {
6068194SJack.Meng@Sun.COM boot_property.boot_tgt.tgt_chap_name =
6078194SJack.Meng@Sun.COM (uchar_t *)kmem_zalloc(
608*10822SJack.Meng@Sun.COM tgtp->rev_chap_name_len + 1,
6098194SJack.Meng@Sun.COM KM_SLEEP);
610*10822SJack.Meng@Sun.COM boot_property.boot_tgt.tgt_chap_name_len
611*10822SJack.Meng@Sun.COM = tgtp->rev_chap_name_len + 1;
6128194SJack.Meng@Sun.COM #define TGT_CHAP_NAME boot_property.boot_tgt.tgt_chap_name
6138194SJack.Meng@Sun.COM tmp = (char *)TGT_CHAP_NAME;
6148194SJack.Meng@Sun.COM #undef TGT_CHAP_NAME
6158194SJack.Meng@Sun.COM (void) snprintf(
6168194SJack.Meng@Sun.COM tmp,
617*10822SJack.Meng@Sun.COM tgtp->rev_chap_name_len + 1,
6188194SJack.Meng@Sun.COM "%s",
6198194SJack.Meng@Sun.COM begin_of_ibft +
6208194SJack.Meng@Sun.COM tgtp->rev_chap_name_offset);
6218194SJack.Meng@Sun.COM } else {
6228194SJack.Meng@Sun.COM /*
6238194SJack.Meng@Sun.COM * Just set NULL, initiator is able
6248194SJack.Meng@Sun.COM * to deal with this
6258194SJack.Meng@Sun.COM */
6268194SJack.Meng@Sun.COM boot_property.boot_tgt.tgt_chap_name =
6278194SJack.Meng@Sun.COM NULL;
6288194SJack.Meng@Sun.COM }
6298194SJack.Meng@Sun.COM
6308194SJack.Meng@Sun.COM if (tgtp->rev_chap_secret_len != 0) {
6318194SJack.Meng@Sun.COM boot_property.boot_tgt.tgt_chap_sec =
6328194SJack.Meng@Sun.COM (uchar_t *)kmem_zalloc(
6338194SJack.Meng@Sun.COM tgtp->rev_chap_secret_len + 1,
6348194SJack.Meng@Sun.COM KM_SLEEP);
635*10822SJack.Meng@Sun.COM boot_property.boot_tgt.tgt_chap_sec_len
636*10822SJack.Meng@Sun.COM = tgtp->rev_chap_secret_len + 1;
6378194SJack.Meng@Sun.COM tmp = (char *)
6388194SJack.Meng@Sun.COM boot_property.boot_tgt.tgt_chap_sec;
6398194SJack.Meng@Sun.COM (void) snprintf(
6408194SJack.Meng@Sun.COM tmp,
6418194SJack.Meng@Sun.COM tgtp->rev_chap_secret_len + 1,
6428194SJack.Meng@Sun.COM "%s",
6438194SJack.Meng@Sun.COM begin_of_ibft +
6448194SJack.Meng@Sun.COM tgtp->chap_secret_offset);
6458194SJack.Meng@Sun.COM } else {
6468194SJack.Meng@Sun.COM boot_property.boot_tgt.tgt_chap_sec =
6478194SJack.Meng@Sun.COM NULL;
6488194SJack.Meng@Sun.COM return (IBFT_STATUS_BADCHAPSEC);
6498194SJack.Meng@Sun.COM }
6508194SJack.Meng@Sun.COM }
6518194SJack.Meng@Sun.COM } else {
6528194SJack.Meng@Sun.COM boot_property.boot_init.ini_chap_name = NULL;
6538194SJack.Meng@Sun.COM boot_property.boot_init.ini_chap_sec = NULL;
6548194SJack.Meng@Sun.COM }
6558194SJack.Meng@Sun.COM
6568194SJack.Meng@Sun.COM /*
6578194SJack.Meng@Sun.COM * Get Boot LUN
6588194SJack.Meng@Sun.COM */
6598194SJack.Meng@Sun.COM (void) bcopy(tgtp->boot_lun,
6608194SJack.Meng@Sun.COM boot_property.boot_tgt.tgt_boot_lun, 8);
6618194SJack.Meng@Sun.COM }
6628194SJack.Meng@Sun.COM
6638194SJack.Meng@Sun.COM return (IBFT_STATUS_OK);
6648194SJack.Meng@Sun.COM }
6658194SJack.Meng@Sun.COM
6668194SJack.Meng@Sun.COM /*
6678194SJack.Meng@Sun.COM * This function is used for scanning iBFT from the physical memory.
6688194SJack.Meng@Sun.COM * Return Value:
6698194SJack.Meng@Sun.COM * IBFT_STATUS_OK
6708194SJack.Meng@Sun.COM * IBFT_STATUS_ERR
6718194SJack.Meng@Sun.COM */
6728194SJack.Meng@Sun.COM static ibft_status_t
iscsi_scan_ibft_tbl(char * ibft_tbl_buf)6738194SJack.Meng@Sun.COM iscsi_scan_ibft_tbl(char *ibft_tbl_buf)
6748194SJack.Meng@Sun.COM {
6758194SJack.Meng@Sun.COM int start;
6768194SJack.Meng@Sun.COM void *va = NULL;
6778194SJack.Meng@Sun.COM int *len = NULL;
6788194SJack.Meng@Sun.COM ibft_status_t ret = IBFT_STATUS_NOTABLE;
6798194SJack.Meng@Sun.COM
6808194SJack.Meng@Sun.COM for (start = ISCSI_IBFT_LOWER_ADDR; start < ISCSI_IBFT_HIGHER_ADDR;
6818194SJack.Meng@Sun.COM start = start + ISCSI_IBFT_ALIGNED) {
6828194SJack.Meng@Sun.COM va = (void *)psm_map((paddr_t)(start&0xffffffff),
6838194SJack.Meng@Sun.COM ISCSI_IBFT_SIGNATURE_LEN,
6848194SJack.Meng@Sun.COM PROT_READ);
6858194SJack.Meng@Sun.COM
6868194SJack.Meng@Sun.COM if (va == NULL) {
6878194SJack.Meng@Sun.COM continue;
6888194SJack.Meng@Sun.COM }
6898194SJack.Meng@Sun.COM if (memcmp(va, ISCSI_IBFT_SIGNATRUE,
6908194SJack.Meng@Sun.COM ISCSI_IBFT_SIGNATURE_LEN) == 0) {
6918194SJack.Meng@Sun.COM ret = IBFT_STATUS_ERR;
6928194SJack.Meng@Sun.COM /* Acquire table length */
6938194SJack.Meng@Sun.COM len = (int *)psm_map(
6948194SJack.Meng@Sun.COM (paddr_t)((start+\
6958194SJack.Meng@Sun.COM ISCSI_IBFT_SIGNATURE_LEN)&0xffffffff),
6968194SJack.Meng@Sun.COM ISCSI_IBFT_SIGNATURE_LEN, PROT_READ);
6978194SJack.Meng@Sun.COM if (len == NULL) {
6988194SJack.Meng@Sun.COM psm_unmap((caddr_t)va,
6998194SJack.Meng@Sun.COM ISCSI_IBFT_SIGNATURE_LEN);
7008194SJack.Meng@Sun.COM continue;
7018194SJack.Meng@Sun.COM }
7028194SJack.Meng@Sun.COM if (ISCSI_IBFT_LOWER_ADDR + *len <
7038194SJack.Meng@Sun.COM ISCSI_IBFT_HIGHER_ADDR - 1) {
7048194SJack.Meng@Sun.COM psm_unmap(va,
7058194SJack.Meng@Sun.COM ISCSI_IBFT_SIGNATURE_LEN);
7068194SJack.Meng@Sun.COM va = psm_map((paddr_t)(start&0xffffffff),
7078194SJack.Meng@Sun.COM *len,
7088194SJack.Meng@Sun.COM PROT_READ);
7098194SJack.Meng@Sun.COM if (va != NULL) {
7108194SJack.Meng@Sun.COM /*
7118194SJack.Meng@Sun.COM * Copy data to our own buffer
7128194SJack.Meng@Sun.COM */
7138194SJack.Meng@Sun.COM bcopy(va, ibft_tbl_buf, *len);
7148194SJack.Meng@Sun.COM ret = IBFT_STATUS_OK;
7158194SJack.Meng@Sun.COM }
7168194SJack.Meng@Sun.COM psm_unmap((caddr_t)va, *len);
7178194SJack.Meng@Sun.COM psm_unmap((caddr_t)len,
7188194SJack.Meng@Sun.COM ISCSI_IBFT_SIGNATURE_LEN);
7198194SJack.Meng@Sun.COM break;
7208194SJack.Meng@Sun.COM } else {
7218194SJack.Meng@Sun.COM psm_unmap((caddr_t)va,
7228194SJack.Meng@Sun.COM ISCSI_IBFT_SIGNATURE_LEN);
7238194SJack.Meng@Sun.COM psm_unmap((caddr_t)len,
7248194SJack.Meng@Sun.COM ISCSI_IBFT_SIGNATURE_LEN);
7258194SJack.Meng@Sun.COM }
7268194SJack.Meng@Sun.COM } else {
7278194SJack.Meng@Sun.COM psm_unmap((caddr_t)va, ISCSI_IBFT_SIGNATURE_LEN);
7288194SJack.Meng@Sun.COM }
7298194SJack.Meng@Sun.COM }
7308194SJack.Meng@Sun.COM
7318194SJack.Meng@Sun.COM return (ret);
7328194SJack.Meng@Sun.COM }
7338194SJack.Meng@Sun.COM
7348194SJack.Meng@Sun.COM /*
7358194SJack.Meng@Sun.COM * Scan the ibft table and store the iSCSI boot properties
7368194SJack.Meng@Sun.COM * If there is a valid table then set the iscsiboot_prop
7378194SJack.Meng@Sun.COM * iBF should be off if the host is not intended
7388194SJack.Meng@Sun.COM * to be booted from iSCSI disk
7398194SJack.Meng@Sun.COM */
7408194SJack.Meng@Sun.COM void
ld_ib_prop()7418194SJack.Meng@Sun.COM ld_ib_prop()
7428194SJack.Meng@Sun.COM {
7438194SJack.Meng@Sun.COM ibft_status_t ret = IBFT_STATUS_OK;
7448194SJack.Meng@Sun.COM char *ibft_tbl_buf;
7458194SJack.Meng@Sun.COM
7468953SVitezslav.Batrla@Sun.COM if (do_bsys_getproplen(NULL, "ibft-noprobe") > 0)
7478953SVitezslav.Batrla@Sun.COM ibft_noprobe = 1;
7488953SVitezslav.Batrla@Sun.COM
7498953SVitezslav.Batrla@Sun.COM if (ibft_noprobe != 0) {
7508953SVitezslav.Batrla@Sun.COM /*
7518953SVitezslav.Batrla@Sun.COM * Scanning for iBFT may conflict with devices which use memory
7528953SVitezslav.Batrla@Sun.COM * in 640-1024KB of physical address space. The iBFT
7538953SVitezslav.Batrla@Sun.COM * specification suggests use of low RAM method - scanning
7548953SVitezslav.Batrla@Sun.COM * physical memory 512-1024 KB for iBFT table. However, the
7558953SVitezslav.Batrla@Sun.COM * Upper Memory Area (UMA) 640-1024 KB may contain device
7568953SVitezslav.Batrla@Sun.COM * memory or memory mapped I/O. Although reading from I/O area
7578953SVitezslav.Batrla@Sun.COM * is usually fine, the actual behavior depends on device
7588953SVitezslav.Batrla@Sun.COM * implementation. In some cases, the user may want to disable
7598953SVitezslav.Batrla@Sun.COM * low RAM method and prevent reading from device I/O area.
7608953SVitezslav.Batrla@Sun.COM *
7618953SVitezslav.Batrla@Sun.COM * To disable low RAM method:
7628953SVitezslav.Batrla@Sun.COM * 1) pass "-B ibft-noprobe=1" on kernel command line
7638953SVitezslav.Batrla@Sun.COM * 2) add line "set ibft_noprobe=1" in /etc/system
7648953SVitezslav.Batrla@Sun.COM */
7658953SVitezslav.Batrla@Sun.COM cmn_err(CE_NOTE, IBFT_NOPROBE_MSG);
7668953SVitezslav.Batrla@Sun.COM return;
7678953SVitezslav.Batrla@Sun.COM }
7688953SVitezslav.Batrla@Sun.COM
7698194SJack.Meng@Sun.COM ibft_tbl_buf = (char *)kmem_zalloc(ISCSI_IBFT_TBL_BUF_LEN,
7708194SJack.Meng@Sun.COM KM_SLEEP);
7718194SJack.Meng@Sun.COM
7728194SJack.Meng@Sun.COM if (!ibft_tbl_buf) {
7738194SJack.Meng@Sun.COM /* Unlikely to happen */
7748194SJack.Meng@Sun.COM cmn_err(CE_NOTE, IBFT_INVALID_MSG,
7758194SJack.Meng@Sun.COM IBFT_STATUS_LOWMEM);
7768194SJack.Meng@Sun.COM return;
7778194SJack.Meng@Sun.COM }
7788194SJack.Meng@Sun.COM
7798194SJack.Meng@Sun.COM (void) memset(&boot_property, 0, sizeof (boot_property));
7808194SJack.Meng@Sun.COM if ((ret = iscsi_scan_ibft_tbl(ibft_tbl_buf)) ==
7818194SJack.Meng@Sun.COM IBFT_STATUS_OK) {
7828194SJack.Meng@Sun.COM ret = iscsi_parse_ibft_tbl(
7838194SJack.Meng@Sun.COM (iscsi_ibft_tbl_hdr_t *)ibft_tbl_buf);
7848194SJack.Meng@Sun.COM if (ret == IBFT_STATUS_OK) {
7858194SJack.Meng@Sun.COM iscsiboot_prop = &boot_property;
7868194SJack.Meng@Sun.COM iscsi_print_boot_property();
7878194SJack.Meng@Sun.COM } else {
7888194SJack.Meng@Sun.COM cmn_err(CE_NOTE, IBFT_INVALID_MSG, ret);
7898194SJack.Meng@Sun.COM }
7908194SJack.Meng@Sun.COM } else if (ret != IBFT_STATUS_NOTABLE) {
7918194SJack.Meng@Sun.COM cmn_err(CE_NOTE, IBFT_INVALID_MSG, ret);
7928194SJack.Meng@Sun.COM }
7938194SJack.Meng@Sun.COM
7948194SJack.Meng@Sun.COM kmem_free(ibft_tbl_buf, ISCSI_IBFT_TBL_BUF_LEN);
7958194SJack.Meng@Sun.COM }
796