boot_loader_openfirmware: Add iSCSI boot support

If no Haiku remote disk server is found, try an iSCSI discovery session on
the TFTP server, using the IP address from the boot command or OF options.
All available IPv4 targets are considered, Target Portal Groups are ignored.

RFC 4173 suggests a mechanism that avoids a discovery session by using DHCP;
that requires a compatibly configured DHCP server though and we wouldn't have
access to such data currently anyway. iSCSI is currently used as fallback,
and when it doesn't succeed it falls back to the menu as before.

Resolves ticket #5319.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@38537 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Andreas Färber
2010-09-05 22:56:22 +00:00
parent 5b086e27e8
commit 3243de5750
@@ -1,5 +1,6 @@
/*
* Copyright 2003-2006, Axel Dörfler, [email protected].
* Copyright 2010, Andreas Färber <[email protected]>
* All rights reserved. Distributed under the terms of the MIT License.
*/
@@ -10,6 +11,8 @@
#include <boot/vfs.h>
#include <boot/stdio.h>
#include <boot/stage2.h>
#include <boot/net/IP.h>
#include <boot/net/iSCSITarget.h>
#include <boot/net/NetStack.h>
#include <boot/net/RemoteDisk.h>
#include <platform/openfirmware/devices.h>
@@ -20,6 +23,9 @@
#include "machine.h"
#define ENABLE_ISCSI
char sBootPath[192];
@@ -46,14 +52,45 @@ platform_add_boot_device(struct stage2_args *args, NodeList *devicesList)
status_t error = net_stack_init();
if (error != B_OK)
return error;
ip_addr_t bootAddress = 0;
char* bootArgs = strrchr(sBootPath, ':');
if (bootArgs != NULL) {
bootArgs++;
char* comma = strchr(bootArgs, ',');
if (comma != NULL && comma - bootArgs > 0) {
comma[0] = '\0';
bootAddress = ip_parse_address(bootArgs);
comma[0] = ',';
}
}
if (bootAddress == 0) {
int package = of_finddevice("/options");
char defaultServerIP[16];
int bytesRead = of_getprop(package, "default-server-ip",
defaultServerIP, sizeof(defaultServerIP) - 1);
if (bytesRead != OF_FAILED && bytesRead > 1) {
defaultServerIP[bytesRead] = '\0';
bootAddress = ip_parse_address(defaultServerIP);
}
}
// init a remote disk, if possible
RemoteDisk *remoteDisk = RemoteDisk::FindAnyRemoteDisk();
if (!remoteDisk)
return B_ENTRY_NOT_FOUND;
if (remoteDisk != NULL) {
devicesList->Add(remoteDisk);
return B_OK;
}
devicesList->Add(remoteDisk);
return B_OK;
#ifdef ENABLE_ISCSI
if (bootAddress != 0) {
if (iSCSITarget::DiscoverTargets(bootAddress, ISCSI_PORT,
devicesList))
return B_OK;
}
#endif
return B_ENTRY_NOT_FOUND;
}
if (strcmp("block", type) != 0) {