summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorJack Meng <Jack.Meng@Sun.COM>2009-10-21 11:28:57 +0800
committerJack Meng <Jack.Meng@Sun.COM>2009-10-21 11:28:57 +0800
commitdedec472759b1a1a25044d504201ef59ccbffb56 (patch)
treec2b74ed12b9e160d396751f8d912f5631a3e5b0c /usr/src
parent89e1f902f752842a275fadd3481dd907e0a1a82a (diff)
downloadillumos-gate-dedec472759b1a1a25044d504201ef59ccbffb56.tar.gz
PSARC 2008/427 iSCSI Boot
PSARC 2009/480 Add bootpath into Solaris Sparc BootArchive for iSCSI boot 6714847 iSCSI boot,sparc part
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/uts/common/fs/vfs.c8
-rw-r--r--usr/src/uts/common/fs/zfs/spa.c13
-rw-r--r--usr/src/uts/common/io/idm/idm_so.c20
-rw-r--r--usr/src/uts/common/io/scsi/adapters/iscsi/iscsi_login.c5
-rw-r--r--usr/src/uts/common/io/scsi/adapters/iscsi/iscsi_net.c12
-rw-r--r--usr/src/uts/common/io/strplumb.c27
-rw-r--r--usr/src/uts/common/os/devcfg.c43
-rw-r--r--usr/src/uts/common/os/iscsiboot_prop.c136
-rw-r--r--usr/src/uts/common/os/swapgeneric.c152
-rw-r--r--usr/src/uts/common/sys/bootprops.h37
-rw-r--r--usr/src/uts/common/sys/idm/idm.h1
-rw-r--r--usr/src/uts/i86pc/os/ibft.c16
-rw-r--r--usr/src/uts/sparc/os/iscsi_boot.c432
13 files changed, 849 insertions, 53 deletions
diff --git a/usr/src/uts/common/fs/vfs.c b/usr/src/uts/common/fs/vfs.c
index 0d750e00ed..6d494c7516 100644
--- a/usr/src/uts/common/fs/vfs.c
+++ b/usr/src/uts/common/fs/vfs.c
@@ -4491,7 +4491,6 @@ extern int hvmboot_rootconf();
#endif /* __x86 */
extern ib_boot_prop_t *iscsiboot_prop;
-extern void iscsi_boot_prop_free();
int
rootconf()
@@ -4544,8 +4543,13 @@ rootconf()
return (EINVAL);
}
- if (netboot || iscsiboot_prop)
+ if (netboot || iscsiboot_prop) {
ret = strplumb();
+ if (ret != 0) {
+ cmn_err(CE_WARN, "Cannot plumb network device %d", ret);
+ return (EFAULT);
+ }
+ }
if ((ret == 0) && iscsiboot_prop) {
ret = modload("drv", "iscsi");
diff --git a/usr/src/uts/common/fs/zfs/spa.c b/usr/src/uts/common/fs/zfs/spa.c
index e242926b5a..4c44d3d76a 100644
--- a/usr/src/uts/common/fs/zfs/spa.c
+++ b/usr/src/uts/common/fs/zfs/spa.c
@@ -64,6 +64,7 @@
#ifdef _KERNEL
#include <sys/zone.h>
+#include <sys/bootprops.h>
#endif /* _KERNEL */
#include "zfs_prop.h"
@@ -2420,7 +2421,17 @@ spa_import_rootpool(char *devpath, char *devid)
/*
* Read the label from the boot device and generate a configuration.
*/
- if ((config = spa_generate_rootconf(devpath, devid, &guid)) == NULL) {
+ config = spa_generate_rootconf(devpath, devid, &guid);
+#if defined(_OBP) && defined(_KERNEL)
+ if (config == NULL) {
+ if (strstr(devpath, "/iscsi/ssd") != NULL) {
+ /* iscsi boot */
+ get_iscsi_bootpath_phy(devpath);
+ config = spa_generate_rootconf(devpath, devid, &guid);
+ }
+ }
+#endif
+ if (config == NULL) {
cmn_err(CE_NOTE, "Can not read the pool label from '%s'",
devpath);
return (EIO);
diff --git a/usr/src/uts/common/io/idm/idm_so.c b/usr/src/uts/common/io/idm/idm_so.c
index ecb2b427f4..fce503b97d 100644
--- a/usr/src/uts/common/io/idm/idm_so.c
+++ b/usr/src/uts/common/io/idm/idm_so.c
@@ -68,7 +68,8 @@ static idm_status_t idm_so_conn_create_common(idm_conn_t *ic, ksocket_t new_so);
static void idm_so_conn_destroy_common(idm_conn_t *ic);
static void idm_so_conn_connect_common(idm_conn_t *ic);
-static void idm_set_ini_preconnect_options(idm_so_conn_t *sc);
+static void idm_set_ini_preconnect_options(idm_so_conn_t *sc,
+ boolean_t boot_conn);
static void idm_set_ini_postconnect_options(idm_so_conn_t *sc);
static void idm_set_tgt_connect_options(ksocket_t so);
static idm_status_t idm_i_so_tx(idm_pdu_t *pdu);
@@ -685,7 +686,7 @@ idm_iov_sorecv(ksocket_t so, iovec_t *iop, int iovlen, size_t total_len)
}
static void
-idm_set_ini_preconnect_options(idm_so_conn_t *sc)
+idm_set_ini_preconnect_options(idm_so_conn_t *sc, boolean_t boot_conn)
{
int conn_abort = 10000;
int conn_notify = 2000;
@@ -695,11 +696,14 @@ idm_set_ini_preconnect_options(idm_so_conn_t *sc)
(void) ksocket_setsockopt(sc->ic_so, IPPROTO_TCP,
TCP_CONN_NOTIFY_THRESHOLD, (char *)&conn_notify, sizeof (int),
CRED());
- (void) ksocket_setsockopt(sc->ic_so, IPPROTO_TCP,
- TCP_CONN_ABORT_THRESHOLD, (char *)&conn_abort, sizeof (int),
- CRED());
- (void) ksocket_setsockopt(sc->ic_so, IPPROTO_TCP, TCP_ABORT_THRESHOLD,
- (char *)&abort, sizeof (int), CRED());
+ if (boot_conn == B_FALSE) {
+ (void) ksocket_setsockopt(sc->ic_so, IPPROTO_TCP,
+ TCP_CONN_ABORT_THRESHOLD, (char *)&conn_abort, sizeof (int),
+ CRED());
+ (void) ksocket_setsockopt(sc->ic_so, IPPROTO_TCP,
+ TCP_ABORT_THRESHOLD,
+ (char *)&abort, sizeof (int), CRED());
+ }
}
static void
@@ -866,7 +870,7 @@ idm_so_ini_conn_create(idm_conn_req_t *cr, idm_conn_t *ic)
so_conn = ic->ic_transport_private;
/* Set up socket options */
- idm_set_ini_preconnect_options(so_conn);
+ idm_set_ini_preconnect_options(so_conn, cr->cr_boot_conn);
return (IDM_STATUS_SUCCESS);
}
diff --git a/usr/src/uts/common/io/scsi/adapters/iscsi/iscsi_login.c b/usr/src/uts/common/io/scsi/adapters/iscsi/iscsi_login.c
index 3ebee23692..5f821deb95 100644
--- a/usr/src/uts/common/io/scsi/adapters/iscsi/iscsi_login.c
+++ b/usr/src/uts/common/io/scsi/adapters/iscsi/iscsi_login.c
@@ -2150,6 +2150,11 @@ iscsi_login_connect(iscsi_conn_t *icp)
sizeof (cr.cr_ini_dst_addr));
bcopy(&icp->conn_bound_addr, &cr.cr_bound_addr,
sizeof (cr.cr_bound_addr));
+ if (isp->sess_boot == B_TRUE) {
+ cr.cr_boot_conn = B_TRUE;
+ } else {
+ cr.cr_boot_conn = B_FALSE;
+ }
/*
* Allocate IDM connection context
diff --git a/usr/src/uts/common/io/scsi/adapters/iscsi/iscsi_net.c b/usr/src/uts/common/io/scsi/adapters/iscsi/iscsi_net.c
index 7a5d0b3133..94481fe9cc 100644
--- a/usr/src/uts/common/io/scsi/adapters/iscsi/iscsi_net.c
+++ b/usr/src/uts/common/io/scsi/adapters/iscsi/iscsi_net.c
@@ -910,8 +910,16 @@ iscsi_net_interface()
/* initialize interface */
if (t_kopen((file_t *)NULL, dl_udp_netconf.knc_rdev,
FREAD|FWRITE, &tiptr, CRED()) == 0) {
- if (kdlifconfig(tiptr, AF_INET, &myaddr, &subnet,
- &braddr, &defgateway, ifname)) {
+ int ret = 0;
+ if (defgateway.s_addr == 0) {
+ /* No default gate way specified */
+ ret = kdlifconfig(tiptr, AF_INET, &myaddr,
+ &subnet, &braddr, NULL, ifname);
+ } else {
+ ret = kdlifconfig(tiptr, AF_INET, &myaddr,
+ &subnet, &braddr, &defgateway, ifname);
+ }
+ if (ret != 0) {
cmn_err(CE_WARN, "Failed to configure"
" iSCSI boot nic");
(void) t_kclose(tiptr, 0);
diff --git a/usr/src/uts/common/io/strplumb.c b/usr/src/uts/common/io/strplumb.c
index 33406bea05..f43648fd7f 100644
--- a/usr/src/uts/common/io/strplumb.c
+++ b/usr/src/uts/common/io/strplumb.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -426,8 +426,6 @@ setifname(ldi_handle_t lh, struct lifreq *lifrp)
return (ldi_ioctl(lh, I_STR, (intptr_t)&iocb, FKIOCTL, CRED(), &rval));
}
-extern ib_boot_prop_t *iscsiboot_prop;
-
static int
strplumb_dev(ldi_ident_t li)
{
@@ -659,15 +657,32 @@ char *
strplumb_get_netdev_path(void)
{
#ifdef _OBP
- char fstype[OBP_MAXPROPNAME];
+ char fstype[OBP_MAXPROPNAME];
+ static char iscsi_network_path[BO_MAXOBJNAME] = {0};
+ int proplen;
+ char *p = NULL;
if (bop_getprop("fstype", fstype) == -1)
return (NULL);
if (strncmp(fstype, "nfs", 3) == 0)
return (prom_bootpath());
- else
- return (NULL);
+ else if (iscsiboot_prop != NULL) {
+ proplen = BOP_GETPROPLEN(bootops,
+ BP_ISCSI_NETWORK_BOOTPATH);
+ if (proplen > 0) {
+ if (BOP_GETPROP(bootops,
+ BP_ISCSI_NETWORK_BOOTPATH,
+ iscsi_network_path) > 0) {
+ p = strchr(iscsi_network_path, ':');
+ if (p != NULL) {
+ *p = '\0';
+ }
+ return (iscsi_network_path);
+ }
+ }
+ }
+ return (NULL);
#else
char *macstr, *devpath = NULL;
diff --git a/usr/src/uts/common/os/devcfg.c b/usr/src/uts/common/os/devcfg.c
index 0c35c932ba..f1fc739b97 100644
--- a/usr/src/uts/common/os/devcfg.c
+++ b/usr/src/uts/common/os/devcfg.c
@@ -55,6 +55,8 @@
#include <sys/fs/sdev_impl.h>
#include <sys/sunldi.h>
#include <sys/sunldi_impl.h>
+#include <sys/bootprops.h>
+
#if defined(__i386) || defined(__amd64)
#if !defined(__xpv)
@@ -3607,6 +3609,38 @@ ddi_find_devinfo(char *nodename, int instance, int attached)
return (info.dip);
}
+extern ib_boot_prop_t *iscsiboot_prop;
+static void
+i_ddi_parse_iscsi_name(char *name, char **nodename, char **addrname,
+ char **minorname)
+{
+ char *cp, *colon;
+ static char nulladdrname[] = "";
+
+ /* default values */
+ if (nodename)
+ *nodename = name;
+ if (addrname)
+ *addrname = nulladdrname;
+ if (minorname)
+ *minorname = NULL;
+
+ cp = colon = name;
+ while (*cp != '\0') {
+ if (addrname && *cp == '@') {
+ *addrname = cp + 1;
+ *cp = '\0';
+ } else if (minorname && *cp == ':') {
+ *minorname = cp + 1;
+ colon = cp;
+ }
+ ++cp;
+ }
+ if (colon != name) {
+ *colon = '\0';
+ }
+}
+
/*
* Parse for name, addr, and minor names. Some args may be NULL.
*/
@@ -3779,8 +3813,13 @@ resolve_pathname(char *pathname,
/* Get component and chop off minorname */
(void) pn_getcomponent(&pn, component);
- i_ddi_parse_name(component, NULL, NULL, &minorname);
-
+ if ((iscsiboot_prop != NULL) &&
+ (strcmp((DEVI(parent)->devi_node_name), "iscsi") == 0)) {
+ i_ddi_parse_iscsi_name(component, NULL, NULL,
+ &minorname);
+ } else {
+ i_ddi_parse_name(component, NULL, NULL, &minorname);
+ }
if (prev_minor == NULL) {
(void) snprintf(config_name, MAXNAMELEN, "%s",
component);
diff --git a/usr/src/uts/common/os/iscsiboot_prop.c b/usr/src/uts/common/os/iscsiboot_prop.c
index 28b0566d34..e803fefc0f 100644
--- a/usr/src/uts/common/os/iscsiboot_prop.c
+++ b/usr/src/uts/common/os/iscsiboot_prop.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -50,6 +50,8 @@ int iscsi_print_bootprop = 0;
#define NULL 0
#endif
+static int replace_sp_c(unsigned char *dst, unsigned char *source, size_t n);
+
static void
iscsi_bootprop_print(int level, char *str)
{
@@ -191,18 +193,21 @@ iscsi_boot_free_ini(ib_ini_prop_t *init)
}
if (init->ini_name != NULL) {
- kmem_free(init->ini_name, strlen((char *)init->ini_name) + 1);
+ kmem_free(init->ini_name, init->ini_name_len);
init->ini_name = NULL;
+ init->ini_name_len = 0;
}
if (init->ini_chap_name != NULL) {
kmem_free(init->ini_chap_name,
- strlen((char *)init->ini_chap_name) + 1);
+ init->ini_chap_name_len);
init->ini_chap_name = NULL;
+ init->ini_chap_name_len = 0;
}
if (init->ini_chap_sec != NULL) {
kmem_free(init->ini_chap_sec,
- strlen((char *)init->ini_chap_sec) + 1);
+ init->ini_chap_sec_len);
init->ini_chap_sec = NULL;
+ init->ini_chap_sec_len = 0;
}
}
@@ -215,18 +220,27 @@ iscsi_boot_free_tgt(ib_tgt_prop_t *target)
if (target->tgt_name != NULL) {
kmem_free(target->tgt_name,
- strlen((char *)target->tgt_name) + 1);
+ target->tgt_name_len);
target->tgt_name = NULL;
+ target->tgt_name_len = 0;
}
if (target->tgt_chap_name != NULL) {
kmem_free(target->tgt_chap_name,
- strlen((char *)target->tgt_chap_name) + 1);
+ target->tgt_chap_name_len);
target->tgt_chap_name = NULL;
+ target->tgt_chap_name_len = 0;
}
if (target->tgt_chap_sec != NULL) {
kmem_free(target->tgt_chap_sec,
- strlen((char *)target->tgt_chap_sec) + 1);
+ target->tgt_chap_sec_len);
target->tgt_chap_sec = NULL;
+ target->tgt_chap_sec_len = 0;
+ }
+ if (target->tgt_boot_par != NULL) {
+ kmem_free(target->tgt_boot_par,
+ target->tgt_boot_par_len);
+ target->tgt_boot_par = NULL;
+ target->tgt_boot_par_len = 0;
}
}
@@ -267,3 +281,111 @@ kinet_ntoa(char *buf, void *in, int af)
(void) sprintf(buf, "%02x%02x", p[i], p[i+1]);
}
}
+
+#ifndef BO_MAXOBJNAME
+#define BO_MAXOBJNAME 256
+#endif
+
+#ifndef ISCSI_BOOT_ISID
+#define ISCSI_BOOT_ISID "0000"
+#endif
+
+/*
+ * Generate the 'ssd' bootpath of an iSCSI boot device
+ * The caller is responsible to alloc the buf with BO_MAXOBJNAME length
+ */
+void
+get_iscsi_bootpath_vhci(char *bootpath)
+{
+ uint16_t *lun_num;
+
+ if (iscsiboot_prop == NULL)
+ ld_ib_prop();
+ if (iscsiboot_prop == NULL)
+ return;
+ lun_num = (uint16_t *)(&iscsiboot_prop->boot_tgt.tgt_boot_lun[0]);
+ (void) snprintf(bootpath, BO_MAXOBJNAME, "/iscsi/ssd@%s%s%04X,%d:%s",
+ ISCSI_BOOT_ISID, iscsiboot_prop->boot_tgt.tgt_name,
+ iscsiboot_prop->boot_tgt.tgt_tpgt, lun_num[0],
+ iscsiboot_prop->boot_tgt.tgt_boot_par);
+}
+
+/*
+ * Generate the 'disk' bootpath of an iSCSI boot device
+ * The caller is responsible to alloc the buf with BO_MAXOBJNAME length
+ */
+void
+get_iscsi_bootpath_phy(char *bootpath)
+{
+ uint16_t lun_num = 0;
+ uchar_t replaced_name[BO_MAXOBJNAME] = {0};
+
+ if (iscsiboot_prop == NULL)
+ ld_ib_prop();
+ if (iscsiboot_prop == NULL)
+ return;
+ if (replace_sp_c(replaced_name, iscsiboot_prop->boot_tgt.tgt_name,
+ iscsiboot_prop->boot_tgt.tgt_name_len) != 0) {
+ return;
+ }
+ lun_num = *(uint16_t *)(&iscsiboot_prop->boot_tgt.tgt_boot_lun[0]);
+ (void) snprintf(bootpath, BO_MAXOBJNAME, "/iscsi/disk@%s%s%04X,%d:%s",
+ ISCSI_BOOT_ISID, replaced_name, iscsiboot_prop->boot_tgt.tgt_tpgt,
+ lun_num, iscsiboot_prop->boot_tgt.tgt_boot_par);
+}
+
+static int replace_sp_c(unsigned char *dst, unsigned char *source, size_t n)
+{
+ unsigned char *p = NULL;
+ int i = 0;
+
+ if (source == NULL || dst == NULL || n == 0) {
+ return (-1);
+ }
+
+ for (p = source; *p != '\0'; p++, i++) {
+ if (i >= n) {
+ return (-1);
+ }
+ switch (*p) {
+ case ':':
+ *dst = '%';
+ dst++;
+ *dst = '3';
+ dst++;
+ *dst = 'A';
+ dst++;
+ break;
+ case ' ':
+ *dst = '%';
+ dst++;
+ *dst = '2';
+ dst++;
+ *dst = '0';
+ dst++;
+ break;
+ case '@':
+ *dst = '%';
+ dst++;
+ *dst = '4';
+ dst++;
+ *dst = '0';
+ dst++;
+ break;
+ case '/':
+ *dst = '%';
+ dst++;
+ *dst = '2';
+ dst++;
+ *dst = 'F';
+ dst++;
+ break;
+ default:
+ *dst = *p;
+ dst++;
+ }
+ }
+ *dst = '\0';
+
+ return (0);
+}
diff --git a/usr/src/uts/common/os/swapgeneric.c b/usr/src/uts/common/os/swapgeneric.c
index 65254506e4..f5f0d4b94d 100644
--- a/usr/src/uts/common/os/swapgeneric.c
+++ b/usr/src/uts/common/os/swapgeneric.c
@@ -20,7 +20,7 @@
*/
/* ONC_PLUS EXTRACT START */
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* ONC_PLUS EXTRACT END */
@@ -70,7 +70,7 @@
#include <sys/hwconf.h>
#include <sys/dc_ki.h>
#include <sys/promif.h>
-
+#include <sys/bootprops.h>
/*
* Local routines
@@ -83,7 +83,7 @@ static int load_boot_driver(char *drv);
static int load_boot_platform_modules(char *drv);
static dev_info_t *path_to_devinfo(char *path);
static boolean_t netboot_over_ib(char *bootpath);
-
+static boolean_t netboot_over_iscsi(void);
/*
* Module linkage information for the kernel.
@@ -114,16 +114,17 @@ _info(struct modinfo *modinfop)
return (mod_info(&modlinkage, modinfop));
}
+extern ib_boot_prop_t *iscsiboot_prop;
/*
* Configure root file system.
*/
int
rootconf(void)
{
- int error;
- struct vfssw *vsw;
+ int error;
+ struct vfssw *vsw;
extern void pm_init(void);
-
+ int ret = -1;
BMDPRINTF(("rootconf: fstype %s\n", rootfs.bo_fstype));
BMDPRINTF(("rootconf: name %s\n", rootfs.bo_name));
BMDPRINTF(("rootconf: flags 0x%x\n", rootfs.bo_flags));
@@ -186,10 +187,34 @@ rootconf(void)
*/
pm_init();
- if (netboot) {
- if ((error = strplumb()) != 0) {
- cmn_err(CE_CONT, "Cannot plumb network device\n");
- return (error);
+ if (netboot && iscsiboot_prop) {
+ cmn_err(CE_WARN, "NFS boot and iSCSI boot"
+ " shouldn't happen in the same time");
+ return (EINVAL);
+ }
+
+ if (netboot || iscsiboot_prop) {
+ ret = strplumb();
+ if (ret != 0) {
+ cmn_err(CE_WARN, "Cannot plumb network device %d", ret);
+ return (EFAULT);
+ }
+ }
+
+ if ((ret == 0) && iscsiboot_prop) {
+ ret = modload("drv", "iscsi");
+ /* -1 indicates fail */
+ if (ret == -1) {
+ cmn_err(CE_WARN, "Failed to load iscsi module");
+ iscsi_boot_prop_free();
+ return (EINVAL);
+ } else {
+ if (!i_ddi_attach_pseudo_node("iscsi")) {
+ cmn_err(CE_WARN,
+ "Failed to attach iscsi driver");
+ iscsi_boot_prop_free();
+ return (ENODEV);
+ }
}
}
@@ -263,7 +288,13 @@ getrootdev(void)
{
dev_t d;
- if ((d = ddi_pathname_to_dev_t(rootfs.bo_name)) == NODEV)
+ d = ddi_pathname_to_dev_t(rootfs.bo_name);
+ if ((d == NODEV) && (iscsiboot_prop != NULL)) {
+ /* Give it another try with the 'disk' path */
+ get_iscsi_bootpath_phy(rootfs.bo_name);
+ d = ddi_pathname_to_dev_t(rootfs.bo_name);
+ }
+ if (d == NODEV)
cmn_err(CE_CONT, "Cannot assemble drivers for root %s\n",
rootfs.bo_name);
return (d);
@@ -378,7 +409,6 @@ loadrootmodules(void)
loop:
(void) getphysdev("root", rootfs.bo_name, BO_MAXOBJNAME);
-
/*
* Given a physical pathname, load the correct set of driver
* modules into memory, including all possible parents.
@@ -508,7 +538,40 @@ loop:
goto out;
}
}
-
+ if (netboot_over_iscsi() == B_TRUE) {
+ /* iscsi boot */
+ if ((err = modloadonly("dacf", "net_dacf")) < 0) {
+ cmn_err(CE_CONT, "Cannot load dacf/net_dacf\n");
+ goto out;
+ }
+ if ((err = modload("misc", "tlimod")) < 0) {
+ cmn_err(CE_CONT, "Cannot load misc/tlimod\n");
+ goto out;
+ }
+ if ((err = modload("mac", "mac_ether")) < 0) {
+ cmn_err(CE_CONT, "Cannot load mac/mac_ether\n");
+ goto out;
+ }
+ if ((err = modloadonly("drv", "iscsi")) < 0) {
+ cmn_err(CE_CONT, "Cannot load drv/iscsi\n");
+ goto out;
+ }
+ if ((err = modloadonly("drv", "ssd")) < 0) {
+ cmn_err(CE_CONT, "Cannot load drv/ssd\n");
+ goto out;
+ }
+ if ((err = modloadonly("drv", "sd")) < 0) {
+ cmn_err(CE_CONT, "Cannot load drv/sd\n");
+ goto out;
+ }
+ if ((err = modload("misc", "strplumb")) < 0) {
+ cmn_err(CE_CONT, "Cannot load misc/strplumb\n");
+ goto out;
+ }
+ if ((err = strplumb_load()) < 0) {
+ goto out;
+ }
+ }
/*
* Preload modules needed for booting as a cluster.
*/
@@ -540,6 +603,11 @@ get_bootpath_prop(char *bootpath)
"boot-path", bootpath) == -1)
return (-1);
}
+ if (memcmp(bootpath, BP_ISCSI_DISK,
+ strlen(BP_ISCSI_DISK)) == 0) {
+ /* iscsi boot */
+ get_iscsi_bootpath_vhci(bootpath);
+ }
}
return (0);
}
@@ -837,15 +905,43 @@ load_bootpath_drivers(char *bootpath)
int pathcopy_len;
int rval;
char *p;
+ int proplen;
+ char iscsi_network_path[BO_MAXOBJNAME];
if (bootpath == NULL || *bootpath == 0)
return (-1);
BMDPRINTF(("load_bootpath_drivers: %s\n", bootpath));
-
- pathcopy = i_ddi_strdup(bootpath, KM_SLEEP);
- pathcopy_len = strlen(pathcopy) + 1;
-
+#ifdef _OBP
+ if (netboot_over_iscsi()) {
+ /* iscsi boot */
+ if (root_is_ramdisk) {
+ modloadonly("drv", "ramdisk");
+ }
+ proplen = BOP_GETPROPLEN(bootops, BP_ISCSI_NETWORK_BOOTPATH);
+ if (proplen > 0) {
+ if (BOP_GETPROP(bootops, BP_ISCSI_NETWORK_BOOTPATH,
+ iscsi_network_path) > 0) {
+ p = strchr(iscsi_network_path, ':');
+ if (p != NULL) {
+ *p = '\0';
+ }
+ pathcopy = i_ddi_strdup(iscsi_network_path,
+ KM_SLEEP);
+ pathcopy_len = strlen(pathcopy) + 1;
+ } else {
+ return (-1);
+ }
+ } else {
+ return (-1);
+ }
+ } else {
+#endif
+ pathcopy = i_ddi_strdup(bootpath, KM_SLEEP);
+ pathcopy_len = strlen(pathcopy) + 1;
+#ifdef _OBP
+ }
+#endif
dip = path_to_devinfo(pathcopy);
#if defined(__i386) || defined(__amd64)
@@ -1079,6 +1175,9 @@ netboot_over_ib(char *bootpath)
char devicetype[OBP_MAXDRVNAME];
/* Is this IB node ? */
+ if (node == OBP_BADNODE || node == OBP_NONODE) {
+ return (B_FALSE);
+ }
len = prom_getproplen(node, OBP_DEVICETYPE);
if (len <= 1 || len >= OBP_MAXDRVNAME)
return (B_FALSE);
@@ -1097,3 +1196,22 @@ netboot_over_ib(char *bootpath)
}
return (ret);
}
+
+static boolean_t
+netboot_over_iscsi(void)
+{
+ int proplen;
+ boolean_t ret = B_FALSE;
+ char bootpath[OBP_MAXPATHLEN];
+
+ proplen = BOP_GETPROPLEN(bootops, BP_BOOTPATH);
+ if (proplen > 0) {
+ if (BOP_GETPROP(bootops, BP_BOOTPATH, bootpath) > 0) {
+ if (memcmp(bootpath, BP_ISCSI_DISK,
+ strlen(BP_ISCSI_DISK)) == 0) {
+ ret = B_TRUE;
+ }
+ }
+ }
+ return (ret);
+}
diff --git a/usr/src/uts/common/sys/bootprops.h b/usr/src/uts/common/sys/bootprops.h
index ed6dd8bd7a..d3eec9d2fd 100644
--- a/usr/src/uts/common/sys/bootprops.h
+++ b/usr/src/uts/common/sys/bootprops.h
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -46,7 +46,24 @@ extern "C" {
#define BP_SERVER_PATH "server-path"
#define BP_SERVER_ROOTOPTS "server-rootopts"
#define BP_BOOTP_RESPONSE "bootp-response"
+
+/*
+ * Boot properties related to iscsiboot:
+ */
#define BP_NETWORK_INTERFACE "network-interface"
+#define BP_ISCSI_TARGET_NAME "iscsi-target-name"
+#define BP_ISCSI_TARGET_IP "iscsi-target-ip"
+#define BP_ISCSI_INITIATOR_ID "iscsi-initiator-id"
+#define BP_ISCSI_PORT "iscsi-port"
+#define BP_ISCSI_TPGT "iscsi-tpgt"
+#define BP_ISCSI_LUN "iscsi-lun"
+#define BP_ISCSI_PAR "iscsi-partition"
+#define BP_ISCSI_NETWORK_BOOTPATH "iscsi-network-bootpath"
+#define BP_ISCSI_DISK "/iscsi-hba/disk"
+#define BP_BOOTPATH "bootpath"
+#define BP_CHAP_USER "chap-user"
+#define BP_CHAP_PASSWORD "chap-password"
+#define BP_LOCAL_MAC_ADDRESS "local-mac-address"
/*
* kifconf prototypes
@@ -70,8 +87,11 @@ kifioctl(TIUSER *tiptr, int cmd, struct netbuf *nbuf, char *ifname);
*/
typedef struct _ib_ini_prop {
uchar_t *ini_name;
+ size_t ini_name_len;
uchar_t *ini_chap_name;
+ size_t ini_chap_name_len;
uchar_t *ini_chap_sec;
+ size_t ini_chap_sec_len;
} ib_ini_prop_t;
/*
@@ -109,9 +129,15 @@ typedef struct _ib_tgt_prop {
uint32_t tgt_port;
uchar_t tgt_boot_lun[8];
uchar_t *tgt_name;
+ size_t tgt_name_len;
uchar_t *tgt_chap_name;
+ size_t tgt_chap_name_len;
uchar_t *tgt_chap_sec;
+ size_t tgt_chap_sec_len;
int lun_online;
+ uchar_t *tgt_boot_par;
+ size_t tgt_boot_par_len;
+ uint16_t tgt_tpgt;
} ib_tgt_prop_t;
/*
@@ -126,6 +152,15 @@ typedef struct _ib_boot_prop {
void
ld_ib_prop();
+void
+iscsi_boot_prop_free();
+
+void
+get_iscsi_bootpath_vhci(char *bootpath);
+
+void
+get_iscsi_bootpath_phy(char *bootpath);
+
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/uts/common/sys/idm/idm.h b/usr/src/uts/common/sys/idm/idm.h
index cb5e256ef3..ada422a1b0 100644
--- a/usr/src/uts/common/sys/idm/idm.h
+++ b/usr/src/uts/common/sys/idm/idm.h
@@ -181,6 +181,7 @@ typedef struct {
idm_sockaddr_t cr_ini_dst_addr;
ldi_ident_t cr_li;
idm_conn_ops_t icr_conn_ops;
+ boolean_t cr_boot_conn;
} idm_conn_req_t;
typedef struct {
diff --git a/usr/src/uts/i86pc/os/ibft.c b/usr/src/uts/i86pc/os/ibft.c
index ab7e52e4ae..43ffad5e81 100644
--- a/usr/src/uts/i86pc/os/ibft.c
+++ b/usr/src/uts/i86pc/os/ibft.c
@@ -374,6 +374,8 @@ iscsi_parse_ibft_initiator(char *begin_of_ibft,
boot_property.boot_init.ini_name =
(uchar_t *)kmem_zalloc(
initiator->ini_name_len + 1, KM_SLEEP);
+ boot_property.boot_init.ini_name_len =
+ initiator->ini_name_len + 1;
(void) snprintf(
(char *)boot_property.boot_init.ini_name,
initiator->ini_name_len + 1, "%s",
@@ -543,6 +545,8 @@ iscsi_parse_ibft_target(char *begin_of_ibft, iscsi_ibft_tgt_t *tgtp)
boot_property.boot_tgt.tgt_name =
(uchar_t *)kmem_zalloc(tgtp->target_name_len + 1,
KM_SLEEP);
+ boot_property.boot_tgt.tgt_name_len =
+ tgtp->target_name_len + 1;
(void) snprintf(
(char *)boot_property.boot_tgt.tgt_name,
tgtp->target_name_len + 1, "%s",
@@ -565,6 +569,8 @@ iscsi_parse_ibft_target(char *begin_of_ibft, iscsi_ibft_tgt_t *tgtp)
(uchar_t *)kmem_zalloc(
tgtp->chap_name_len + 1,
KM_SLEEP);
+ boot_property.boot_init.ini_chap_name_len =
+ tgtp->chap_name_len + 1;
tmp = (char *)
boot_property.boot_init.ini_chap_name;
(void) snprintf(
@@ -584,6 +590,8 @@ iscsi_parse_ibft_target(char *begin_of_ibft, iscsi_ibft_tgt_t *tgtp)
(uchar_t *)kmem_zalloc(
tgtp->chap_secret_len + 1,
KM_SLEEP);
+ boot_property.boot_init.ini_chap_sec_len =
+ tgtp->chap_secret_len + 1;
bcopy(begin_of_ibft +
tgtp->chap_secret_offset,
boot_property.boot_init.ini_chap_sec,
@@ -597,14 +605,16 @@ iscsi_parse_ibft_target(char *begin_of_ibft, iscsi_ibft_tgt_t *tgtp)
if (tgtp->rev_chap_name_len != 0) {
boot_property.boot_tgt.tgt_chap_name =
(uchar_t *)kmem_zalloc(
- tgtp->chap_name_len + 1,
+ tgtp->rev_chap_name_len + 1,
KM_SLEEP);
+ boot_property.boot_tgt.tgt_chap_name_len
+ = tgtp->rev_chap_name_len + 1;
#define TGT_CHAP_NAME boot_property.boot_tgt.tgt_chap_name
tmp = (char *)TGT_CHAP_NAME;
#undef TGT_CHAP_NAME
(void) snprintf(
tmp,
- tgtp->chap_name_len + 1,
+ tgtp->rev_chap_name_len + 1,
"%s",
begin_of_ibft +
tgtp->rev_chap_name_offset);
@@ -622,6 +632,8 @@ iscsi_parse_ibft_target(char *begin_of_ibft, iscsi_ibft_tgt_t *tgtp)
(uchar_t *)kmem_zalloc(
tgtp->rev_chap_secret_len + 1,
KM_SLEEP);
+ boot_property.boot_tgt.tgt_chap_sec_len
+ = tgtp->rev_chap_secret_len + 1;
tmp = (char *)
boot_property.boot_tgt.tgt_chap_sec;
(void) snprintf(
diff --git a/usr/src/uts/sparc/os/iscsi_boot.c b/usr/src/uts/sparc/os/iscsi_boot.c
index 4a928c6a0e..78f7e8549c 100644
--- a/usr/src/uts/sparc/os/iscsi_boot.c
+++ b/usr/src/uts/sparc/os/iscsi_boot.c
@@ -19,17 +19,439 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <sys/bootprops.h>
+#include <sys/bootconf.h>
+#include <sys/modctl.h>
+#include <sys/mman.h>
+#include <sys/kmem.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+#include <sys/types.h>
+#include <sys/obpdefs.h>
+#include <sys/promif.h>
+#include <sys/iscsi_protocol.h>
+#define ISCSI_OBP_MAX_CHAP_USER_LEN 16
+#define ISCSI_OBP_MIN_CHAP_LEN 12
+#define ISCSI_OBP_MAX_CHAP_LEN 16
+
+#define OBP_GET_KEY_STATUS_OK 0
+#define OBP_GET_KEY_STATUS_NOT_EXIST -3
+
+ib_boot_prop_t boot_property;
extern ib_boot_prop_t *iscsiboot_prop;
+static int inet_aton(char *ipstr, uchar_t *ip);
+static boolean_t parse_lun_num(uchar_t *str_num, uchar_t *hex_num);
+static void generate_iscsi_initiator_id(void);
+
+static int
+isdigit(int ch)
+{
+ return (ch >= '0' && ch <= '9');
+}
+
+static boolean_t
+iscsiboot_tgt_prop_read(void)
+{
+ int proplen;
+ boolean_t set = B_FALSE;
+ char iscsi_target_ip[INET6_ADDRSTRLEN];
+ uchar_t iscsi_target_name[ISCSI_MAX_NAME_LEN];
+ uchar_t iscsi_par[8];
+ char chap_user[ISCSI_OBP_MAX_CHAP_USER_LEN] = {0};
+ char chap_password[ISCSI_OBP_MAX_CHAP_LEN] = {0};
+ uchar_t iscsi_port[8];
+ uchar_t iscsi_lun[8];
+ uchar_t iscsi_tpgt[8];
+ long iscsi_tpgtl;
+ long port;
+ int ret = 0;
+ int status = 0;
+ int chap_user_len = 0;
+ int chap_pwd_len = 0;
+
+ /* Get iscsi target IP address */
+ proplen = BOP_GETPROPLEN(bootops, BP_ISCSI_TARGET_IP);
+ if (proplen > 0) {
+ if (BOP_GETPROP(bootops, BP_ISCSI_TARGET_IP,
+ iscsi_target_ip) > 0) {
+ if (inet_aton(iscsi_target_ip,
+ (uchar_t *)&boot_property.boot_tgt.tgt_ip_u) ==
+ 0) {
+ boot_property.boot_tgt.sin_family = AF_INET;
+ set = B_TRUE;
+ }
+ }
+ }
+ if (set != B_TRUE) {
+ return (B_FALSE);
+ }
+
+ /* Get iscsi target port number */
+ set = B_FALSE;
+ proplen = BOP_GETPROPLEN(bootops, BP_ISCSI_PORT);
+ if (proplen > 0) {
+ if (BOP_GETPROP(bootops, BP_ISCSI_PORT,
+ iscsi_port) > 0) {
+ if (ddi_strtol((const char *)iscsi_port, NULL,
+ 10, &port) == 0) {
+ boot_property.boot_tgt.tgt_port =
+ (unsigned int)port;
+ set = B_TRUE;
+ }
+ }
+ }
+ if (set != B_TRUE) {
+ boot_property.boot_tgt.tgt_port = 3260;
+ }
+
+ /* Get iscsi target LUN number */
+ set = B_FALSE;
+ proplen = BOP_GETPROPLEN(bootops, BP_ISCSI_LUN);
+ if (proplen > 0) {
+ if (BOP_GETPROP(bootops, BP_ISCSI_LUN,
+ iscsi_lun) > 0) {
+ if (parse_lun_num(iscsi_lun,
+ (uchar_t *)
+ (&boot_property.boot_tgt.tgt_boot_lun[0]))
+ == B_TRUE) {
+ set = B_TRUE;
+ }
+ }
+ }
+ if (set != B_TRUE) {
+ bzero((void *)boot_property.boot_tgt.tgt_boot_lun, 8);
+ }
+
+ /* Get iscsi target portal group tag */
+ set = B_FALSE;
+ proplen = BOP_GETPROPLEN(bootops, BP_ISCSI_TPGT);
+ if (proplen > 0) {
+ if (BOP_GETPROP(bootops, BP_ISCSI_TPGT,
+ iscsi_tpgt) > 0) {
+ if (ddi_strtol((const char *)iscsi_tpgt, NULL, 10,
+ &iscsi_tpgtl) == 0) {
+ boot_property.boot_tgt.tgt_tpgt =
+ (uint16_t)iscsi_tpgtl;
+ set = B_TRUE;
+ }
+ }
+ }
+ if (set != B_TRUE) {
+ boot_property.boot_tgt.tgt_tpgt = 1;
+ }
+
+ /* Get iscsi target node name */
+ set = B_FALSE;
+ boot_property.boot_tgt.tgt_name = NULL;
+ proplen = BOP_GETPROPLEN(bootops, BP_ISCSI_TARGET_NAME);
+ if (proplen > 0) {
+ if (BOP_GETPROP(bootops, BP_ISCSI_TARGET_NAME,
+ iscsi_target_name) > 0) {
+ boot_property.boot_tgt.tgt_name =
+ (uchar_t *)kmem_zalloc(proplen + 1, KM_SLEEP);
+ boot_property.boot_tgt.tgt_name_len = proplen + 1;
+ (void) snprintf((char *)boot_property.boot_tgt.tgt_name,
+ proplen + 1, "%s", iscsi_target_name);
+ set = B_TRUE;
+ }
+ }
+ if (set != B_TRUE) {
+ if (boot_property.boot_tgt.tgt_name != NULL) {
+ kmem_free(boot_property.boot_tgt.tgt_name,
+ boot_property.boot_tgt.tgt_name_len);
+ boot_property.boot_tgt.tgt_name = NULL;
+ boot_property.boot_tgt.tgt_name_len = 0;
+ }
+ return (B_FALSE);
+ }
+
+ /* Get iscsi target boot partition */
+ set = B_FALSE;
+ boot_property.boot_tgt.tgt_boot_par = NULL;
+ boot_property.boot_tgt.tgt_boot_par_len = 0;
+ proplen = BOP_GETPROPLEN(bootops, BP_ISCSI_PAR);
+ if (proplen > 0) {
+ if (BOP_GETPROP(bootops, BP_ISCSI_PAR, iscsi_par) > 0) {
+ boot_property.boot_tgt.tgt_boot_par =
+ (uchar_t *)kmem_zalloc(proplen + 1, KM_SLEEP);
+ boot_property.boot_tgt.tgt_boot_par_len = proplen + 1;
+ (void) snprintf(
+ (char *)boot_property.boot_tgt.tgt_boot_par,
+ proplen + 1, "%s", iscsi_par);
+ set = B_TRUE;
+ }
+ }
+ if (set != B_TRUE) {
+ boot_property.boot_tgt.tgt_boot_par =
+ (uchar_t *)kmem_zalloc(2, KM_SLEEP);
+ boot_property.boot_tgt.tgt_boot_par_len = 2;
+ boot_property.boot_tgt.tgt_boot_par[0] = 'a';
+ }
+
+ /* Get CHAP name and secret */
+ ret = prom_get_security_key(BP_CHAP_USER, chap_user,
+ ISCSI_OBP_MAX_CHAP_USER_LEN, &chap_user_len, &status);
+ if (ret != 0) {
+ return (B_FALSE);
+ }
+ if (status == OBP_GET_KEY_STATUS_NOT_EXIST) {
+ /* No chap name */
+ return (B_TRUE);
+ }
+ if (status != OBP_GET_KEY_STATUS_OK ||
+ chap_user_len > ISCSI_OBP_MAX_CHAP_USER_LEN ||
+ chap_user_len <= 0) {
+ return (B_FALSE);
+ }
+
+ ret = prom_get_security_key(BP_CHAP_PASSWORD, chap_password,
+ ISCSI_OBP_MAX_CHAP_LEN, &chap_pwd_len, &status);
+ if (ret != 0) {
+ return (B_FALSE);
+ }
+
+ if (status == OBP_GET_KEY_STATUS_NOT_EXIST) {
+ /* No chap secret */
+ return (B_TRUE);
+ }
+ if (status != OBP_GET_KEY_STATUS_OK ||
+ chap_pwd_len > ISCSI_OBP_MAX_CHAP_LEN ||
+ chap_pwd_len <= 0) {
+ return (B_FALSE);
+ }
+
+ boot_property.boot_init.ini_chap_name =
+ (uchar_t *)kmem_zalloc(chap_user_len + 1, KM_SLEEP);
+ boot_property.boot_init.ini_chap_name_len = chap_user_len + 1;
+ (void) memcpy(boot_property.boot_init.ini_chap_name, chap_user,
+ chap_user_len);
+
+ boot_property.boot_init.ini_chap_sec =
+ (uchar_t *)kmem_zalloc(chap_pwd_len + 1, KM_SLEEP);
+ boot_property.boot_init.ini_chap_sec_len = chap_pwd_len + 1;
+ (void) memcpy(boot_property.boot_init.ini_chap_sec, chap_password,
+ chap_pwd_len);
+
+ return (B_TRUE);
+}
+
+static boolean_t
+iscsiboot_init_prop_read(void)
+{
+ int proplen;
+ uchar_t iscsi_initiator_id[ISCSI_MAX_NAME_LEN];
+ boolean_t set = B_FALSE;
+
+ /* Get initiator node name */
+ proplen = BOP_GETPROPLEN(bootops, BP_ISCSI_INITIATOR_ID);
+ if (proplen > 0) {
+ if (BOP_GETPROP(bootops, BP_ISCSI_INITIATOR_ID,
+ iscsi_initiator_id) > 0) {
+ boot_property.boot_init.ini_name =
+ (uchar_t *)kmem_zalloc(proplen + 1, KM_SLEEP);
+ boot_property.boot_init.ini_name_len = proplen + 1;
+ (void) snprintf(
+ (char *)boot_property.boot_init.ini_name,
+ proplen + 1, "%s", iscsi_initiator_id);
+ set = B_TRUE;
+ }
+ }
+ if (set != B_TRUE) {
+ generate_iscsi_initiator_id();
+ }
+ return (B_TRUE);
+}
+static boolean_t
+iscsiboot_nic_prop_read(void)
+{
+ int proplen;
+ char host_ip[INET6_ADDRSTRLEN];
+ char router_ip[INET6_ADDRSTRLEN];
+ char subnet_mask[INET6_ADDRSTRLEN];
+ uchar_t iscsi_network_path[MAXPATHLEN];
+ char host_mac[6];
+ uchar_t hex_netmask[4];
+ pnode_t nodeid;
+ boolean_t set = B_FALSE;
+
+ /* Get host IP address */
+ proplen = BOP_GETPROPLEN(bootops, BP_HOST_IP);
+ if (proplen > 0) {
+ if (BOP_GETPROP(bootops, BP_HOST_IP,
+ host_ip) > 0) {
+ if (inet_aton(host_ip,
+ (uchar_t *)&boot_property.boot_nic.nic_ip_u) ==
+ 0) {
+ boot_property.boot_nic.sin_family = AF_INET;
+ set = B_TRUE;
+ }
+ }
+ }
+ if (set != B_TRUE) {
+ return (B_FALSE);
+ }
+
+ /* Get router IP address */
+ proplen = BOP_GETPROPLEN(bootops, BP_ROUTER_IP);
+ if (proplen > 0) {
+ if (BOP_GETPROP(bootops, BP_ROUTER_IP,
+ router_ip) > 0) {
+ (void) inet_aton(router_ip,
+ (uchar_t *)&boot_property.boot_nic.nic_gw_u);
+ }
+ }
+
+ /* Get host netmask */
+ set = B_FALSE;
+ proplen = BOP_GETPROPLEN(bootops, BP_SUBNET_MASK);
+ if (proplen > 0) {
+ if (BOP_GETPROP(bootops, BP_SUBNET_MASK,
+ subnet_mask) > 0) {
+ if (inet_aton(subnet_mask, hex_netmask) == 0) {
+ int i = 0;
+ uint32_t tmp = *((uint32_t *)hex_netmask);
+ while (tmp) {
+ i ++;
+ tmp = tmp << 1;
+ }
+ boot_property.boot_nic.sub_mask_prefix = i;
+ set = B_TRUE;
+ }
+ }
+ }
+ if (set != B_TRUE) {
+ boot_property.boot_nic.sub_mask_prefix = 24;
+ }
+
+ /* Get iscsi boot NIC path in OBP */
+ set = B_FALSE;
+ proplen = BOP_GETPROPLEN(bootops, BP_ISCSI_NETWORK_BOOTPATH);
+ if (proplen > 0) {
+ if (BOP_GETPROP(bootops, BP_ISCSI_NETWORK_BOOTPATH,
+ iscsi_network_path) > 0) {
+ nodeid = prom_finddevice((char *)iscsi_network_path);
+ proplen = prom_getproplen(nodeid, BP_LOCAL_MAC_ADDRESS);
+ if (proplen > 0) {
+ if (prom_getprop(nodeid, BP_LOCAL_MAC_ADDRESS,
+ host_mac) > 0) {
+ (void) memcpy(
+ boot_property.boot_nic.nic_mac,
+ host_mac, 6);
+ set = B_TRUE;
+ }
+ }
+ }
+ }
+ if (set != B_TRUE) {
+ return (B_FALSE);
+ }
+
+ return (B_TRUE);
+}
+
+/*
+ * Manully construct iscsiboot_prop table based on
+ * OBP '/chosen' properties related to iscsi boot
+ */
void
-ld_ib_prop() {
- /*
- * For sparc, do nothing now
- */
+ld_ib_prop()
+{
+ if (iscsiboot_prop != NULL)
+ return;
+
+ if ((iscsiboot_tgt_prop_read() == B_TRUE) &&
+ (iscsiboot_init_prop_read() == B_TRUE) &&
+ (iscsiboot_nic_prop_read() == B_TRUE)) {
+ iscsiboot_prop = &boot_property;
+ } else {
+ iscsi_boot_prop_free();
+ }
+}
+
+static boolean_t
+parse_lun_num(uchar_t *str_num, uchar_t *hex_num)
+{
+ char *p, *buf;
+ uint16_t *conv_num = (uint16_t *)hex_num;
+ long tmp;
+ int i = 0;
+
+ if ((str_num == NULL) || (hex_num == NULL)) {
+ return (B_FALSE);
+ }
+ bzero((void *)hex_num, 8);
+ buf = (char *)str_num;
+
+ for (i = 0; i < 4; i++) {
+ p = NULL;
+ p = strchr((const char *)buf, '-');
+ if (p != NULL) {
+ *p = '\0';
+ }
+ if (ddi_strtol((const char *)buf, NULL, 16, &tmp) != 0) {
+ return (B_FALSE);
+ }
+ conv_num[i] = (uint16_t)tmp;
+ if (p != NULL) {
+ buf = p + 1;
+ } else {
+ break;
+ }
+ }
+
+ return (B_TRUE);
+}
+
+static void
+generate_iscsi_initiator_id(void)
+{
+ boot_property.boot_init.ini_name_len = 38;
+ boot_property.boot_init.ini_name =
+ (uchar_t *)kmem_zalloc(boot_property.boot_init.ini_name_len,
+ KM_SLEEP);
+ (void) snprintf((char *)boot_property.boot_init.ini_name,
+ 38, "iqn.1986-03.com.sun:boot.%02x%02x%02x%02x%02x%02x",
+ boot_property.boot_nic.nic_mac[0],
+ boot_property.boot_nic.nic_mac[1],
+ boot_property.boot_nic.nic_mac[2],
+ boot_property.boot_nic.nic_mac[3],
+ boot_property.boot_nic.nic_mac[4],
+ boot_property.boot_nic.nic_mac[5]);
+}
+
+
+/* We only deal with a.b.c.d decimal format. ip points to 4 byte storage */
+static int
+inet_aton(char *ipstr, uchar_t *ip)
+{
+ int i = 0;
+ uchar_t val[4] = {0};
+ char c = *ipstr;
+
+ for (;;) {
+ if (!isdigit(c))
+ return (-1);
+ for (;;) {
+ if (!isdigit(c))
+ break;
+ val[i] = val[i] * 10 + (c - '0');
+ c = *++ipstr;
+ }
+ i++;
+ if (i == 4)
+ break;
+ if (c != '.')
+ return (-1);
+ c = *++ipstr;
+ }
+ if (c != 0)
+ return (-1);
+ bcopy(val, ip, 4);
+ return (0);
}