diff --git a/headers/private/drivers/iscsi_cmds.h b/headers/private/drivers/iscsi_cmds.h deleted file mode 100644 index 6c4f9e8c56..0000000000 --- a/headers/private/drivers/iscsi_cmds.h +++ /dev/null @@ -1,336 +0,0 @@ -/* - * Copyright 2010, Andreas Färber - * All rights reserved. Distributed under the terms of the MIT License. - */ -#ifndef ISCSI_CMDS_H -#define ISCSI_CMDS_H - - -#include - - -// TODO Add Little Endian support by introducing more macros -#if __BYTE_ORDER != __BIG_ENDIAN -#error Only Big Endian systems supported yet. -#endif - - -// iSCSI Basic Header Segment (BHS) (RFC 3720 10.2.1) - -#define ISCSI_BHS_BYTE0 \ - bool reserved : 1; \ - bool immediateDelivery : 1; \ - uint8 opcode : 6; - -// TODO This macro is LE-incompatible -#define ISCSI_BHS_START \ - ISCSI_BHS_BYTE0 \ - bool final : 1; - -#define ISCSI_BHS_LENGTHS \ - uint8 totalAHSLength; \ - uint32 dataSegmentLength : 24; - -#define ISCSI_BHS_TASK_TAG \ - uint32 initiatorTaskTag; - -#define ISCSI_BHS_TAGS \ - ISCSI_BHS_TASK_TAG \ - uint32 targetTransferTag; - -struct iscsi_basic_header_segment { - ISCSI_BHS_START - uint32 opcodeSpecific : 23; - ISCSI_BHS_LENGTHS - uint64 lun; - ISCSI_BHS_TASK_TAG - uint8 opcodeSpecific2[28]; -} _PACKED; - -// initiator opcodes -#define ISCSI_OPCODE_NOP_OUT 0x00 -#define ISCSI_OPCODE_SCSI_COMMAND 0x01 -#define ISCSI_OPCODE_LOGIN_REQUEST 0x03 -#define ISCSI_OPCODE_TEXT_REQUEST 0x04 -#define ISCSI_OPCODE_LOGOUT_REQUEST 0x06 -// target opcodes -#define ISCSI_OPCODE_NOP_IN 0x20 -#define ISCSI_OPCODE_SCSI_RESPONSE 0x21 -#define ISCSI_OPCODE_LOGIN_RESPONSE 0x23 -#define ISCSI_OPCODE_TEXT_RESPONSE 0x24 -#define ISCSI_OPCODE_SCSI_DATA_IN 0x25 -#define ISCSI_OPCODE_LOGOUT_RESPONSE 0x26 - -// SCSI Command (RFC 3720 10.3) -struct iscsi_scsi_command { - iscsi_scsi_command() - : - reserved(0), - opcode(ISCSI_OPCODE_SCSI_COMMAND), - reserved2(0), - reserved3(0) - { - } - ISCSI_BHS_START - bool r : 1; - bool w : 1; - uint8 reserved2 : 2; - uint8 attr : 3; - uint16 reserved3; - ISCSI_BHS_LENGTHS - uint64 lun; - ISCSI_BHS_TASK_TAG - uint32 expectedDataTransferLength; - uint32 cmdSN; - uint32 expStatSN; - uint8 cdb[16]; -} _PACKED; - -// SCSI Response (RFC 3720 10.4) -struct iscsi_scsi_response { - ISCSI_BHS_START - uint8 reserved2 : 2; - bool o : 1; - bool u : 1; - bool O : 1; - bool U : 1; - bool reserved3 : 1; - uint8 response; - uint8 status; - ISCSI_BHS_LENGTHS - uint32 reserved4[2]; - ISCSI_BHS_TASK_TAG - uint32 snackTag; - uint32 statSN; - uint32 expCmdSN; - uint32 maxCmdSN; - uint32 expDataSN; - uint32 bidirectionalReadResidualCount; - uint32 residualCount; -} _PACKED; - -// SCSI Data-In (RFC 3270 10.7) -struct iscsi_scsi_data_in { - ISCSI_BHS_START - bool acknowledge : 1; - uint8 reserved2 : 3; - bool O : 1; - bool U : 1; - bool S : 1; - uint8 reserved3; - uint8 status; - ISCSI_BHS_LENGTHS - uint64 lun; - ISCSI_BHS_TAGS - uint32 statSN; - uint32 expCmdSN; - uint32 maxCmdSN; - uint32 dataSN; - uint32 bufferOffset; - uint32 residualCount; -} _PACKED; - -// Text Request (RFC 3720 10.10) -struct iscsi_text_request { - iscsi_text_request() - : - reserved(0), - opcode(ISCSI_OPCODE_TEXT_REQUEST), - reserved2(2) - { - reserved3[0] = 0; - reserved3[1] = 0; - reserved3[2] = 0; - reserved3[3] = 0; - } - ISCSI_BHS_START - bool c : 1; // continue - uint32 reserved2 : 22; - ISCSI_BHS_LENGTHS - uint64 lun; - ISCSI_BHS_TAGS - uint32 cmdSN; - uint32 expStatSN; - uint32 reserved3[4]; -} _PACKED; - -// Text Response (RFC 3720 10.11) -struct iscsi_text_response { - ISCSI_BHS_START - bool c : 1; // continue - uint32 reserved2 : 22; - ISCSI_BHS_LENGTHS - uint64 lun; - ISCSI_BHS_TAGS - uint32 statSN; - uint32 expCmdSN; - uint32 maxCmdSN; - uint32 reserved3[3]; -} _PACKED; - -struct iscsi_isid { - uint8 t : 2; - uint8 a : 6; - uint16 b; - uint8 c; - uint16 d; -} _PACKED; - -// Login Request (RFC 3720 10.12) -struct iscsi_login_request { - iscsi_login_request() - : - reserved(false), - immediateDelivery(1), - opcode(ISCSI_OPCODE_LOGIN_REQUEST), - reserved2(0), - reserved3(0) - { - memset(reserved4, 0, sizeof(reserved4)); - } - - ISCSI_BHS_BYTE0 - bool transit : 1; - bool c : 1; // continue - uint8 reserved2 : 2; - uint8 currentStage : 2; - uint8 nextStage : 2; - uint8 versionMax; - uint8 versionMin; - ISCSI_BHS_LENGTHS - iscsi_isid isid; - uint16 tsih; - ISCSI_BHS_TASK_TAG - uint16 cid; - uint16 reserved3; - uint32 cmdSN; - uint32 expStatSN; - uint32 reserved4[4]; -} _PACKED; - -#define ISCSI_SESSION_STAGE_SECURITY_NEGOTIATION 0 -#define ISCSI_SESSION_STAGE_LOGIN_OPERATIONAL_NEGOTIATION 1 -#define ISCSI_SESSION_STAGE_FULL_FEATURE_PHASE 3 - -#define ISCSI_VERSION 0x00 - -#define ISCSI_ISID_OUI 0 -#define ISCSI_ISID_EN 1 -#define ISCSI_ISID_RANDOM 2 - -// Login Response (RFC 3720 10.13) -struct iscsi_login_response { - ISCSI_BHS_BYTE0 - bool transit : 1; - bool c : 1; // continue - uint8 reserved2 : 2; - uint8 currentStage : 2; - uint8 nextStage : 2; - uint8 versionMax; - uint8 versionActive; - ISCSI_BHS_LENGTHS - iscsi_isid isid; - uint16 tsih; - ISCSI_BHS_TASK_TAG - uint32 reserved3; - uint32 statSN; - uint32 expCmdSN; - uint32 maxCmdSN; - uint8 statusClass; - uint8 statusDetail; - uint16 reserved4; - uint32 reserved5[2]; -} _PACKED; - -// Logout Request (RFC 3720 10.14) -struct iscsi_logout_request { - iscsi_logout_request() - : - reserved(0), - opcode(ISCSI_OPCODE_LOGOUT_REQUEST), - final(true), - reserved2(0), - reserved4(0) - { - reserved3[0] = 0; - reserved3[1] = 0; - reserved5[0] = 0; - reserved5[1] = 0; - reserved5[2] = 0; - reserved5[3] = 0; - } - ISCSI_BHS_START - uint8 reasonCode : 7; - uint16 reserved2; - ISCSI_BHS_LENGTHS - uint32 reserved3[2]; - ISCSI_BHS_TASK_TAG - uint16 cid; - uint16 reserved4; - uint32 cmdSN; - uint32 expStatSN; - uint32 reserved5[4]; -} _PACKED; - -#define ISCSI_LOGOUT_REASON_CLOSE_SESSION 0 -#define ISCSI_LOGOUT_REASON_CLOSE_CONNECTION 1 -#define ISCSI_LOGOUT_REASON_REMOVE_CONNECTION 2 - -// Logout Response (RFC 3720 10.15) -struct iscsi_logout_response { - ISCSI_BHS_START - uint8 reserved2 : 7; - uint8 response; - uint8 reserved3; - ISCSI_BHS_LENGTHS - uint32 reserved4[2]; - ISCSI_BHS_TASK_TAG - uint32 reserved5; - uint32 statSN; - uint32 expCmdSN; - uint32 maxCmdSN; - uint32 reserved6; - uint16 time2Wait; - uint16 time2Remain; - uint32 reserved7; -} _PACKED; - -// NOP-Out (RFC 3270, 10.18) -struct iscsi_nop_out { - iscsi_nop_out() - : - reserved(0), - opcode(ISCSI_OPCODE_NOP_OUT), - final(true), - reserved2(0) - { - reserved3[0] = 0; - reserved3[1] = 0; - reserved3[2] = 0; - reserved3[3] = 0; - } - ISCSI_BHS_START - uint32 reserved2 : 23; - ISCSI_BHS_LENGTHS - uint64 lun; - ISCSI_BHS_TAGS - uint32 cmdSN; - uint32 expStatSN; - uint32 reserved3[4]; -} _PACKED; - -// NOP-In (RFC 3270, 10.19) -struct iscsi_nop_in { - ISCSI_BHS_START - uint32 reserved2 : 23; - ISCSI_BHS_LENGTHS - uint64 lun; - ISCSI_BHS_TAGS - uint32 statSN; - uint32 expCmdSN; - uint32 maxCmdSN; - uint32 reserved3[3]; -} _PACKED; - - -#endif diff --git a/src/system/boot/loader/net/Jamfile b/src/system/boot/loader/net/Jamfile index 4ad60ad070..bb6932e545 100644 --- a/src/system/boot/loader/net/Jamfile +++ b/src/system/boot/loader/net/Jamfile @@ -9,13 +9,6 @@ for platform in [ MultiBootSubDirSetup ] { on $(platform) { UsePrivateHeaders kernel [ FDirName kernel boot platform $(TARGET_BOOT_PLATFORM) ] ; - local tcp = ; - local iscsi = ; - if $(TARGET_ARCH) = ppc { - tcp = TCP.cpp ; - iscsi = iSCSITarget.cpp ; - } - BootStaticLibrary [ MultiBootGristFiles boot_net ] : ARP.cpp ChainBuffer.cpp @@ -24,9 +17,8 @@ for platform in [ MultiBootSubDirSetup ] { NetDefs.cpp NetStack.cpp RemoteDisk.cpp + TCP.cpp UDP.cpp - $(tcp) - $(iscsi) ; } } diff --git a/src/system/boot/loader/net/iSCSITarget.cpp b/src/system/boot/loader/net/iSCSITarget.cpp deleted file mode 100644 index dba7a1636a..0000000000 --- a/src/system/boot/loader/net/iSCSITarget.cpp +++ /dev/null @@ -1,822 +0,0 @@ -/* - * Copyright 2010, Andreas Färber - * All rights reserved. Distributed under the terms of the MIT License. - */ - - -#include - -#include -#include -#include - -#include - -#include -#include -#include -#include - -#include "real_time_clock.h" - - -//#define TRACE_ISCSI - -#ifndef TRACE_ISCSI -#define TRACE(fmt, ...) ; -#else -#define TRACE(fmt, ...) printf("iSCSI: %s(): " fmt, __func__, ## __VA_ARGS__) -#endif -#define PANIC(fmt, ...) panic("iSCSI: %s(): " fmt, __func__, ## __VA_ARGS__) - - -#define ISCSI_ALIGNMENT 4 -#define ISCSI_ALIGN(x) (((x) + ISCSI_ALIGNMENT - 1) & ~(ISCSI_ALIGNMENT - 1)) -#define ISCSI_PADDING(x) ((((x) % ISCSI_ALIGNMENT) == 0) ? 0 \ - : (ISCSI_ALIGNMENT - ((x) % ISCSI_ALIGNMENT))) - -// derived from the schedulers -static int -_rand(void) -{ - static int next = 0; - if (next == 0) - next = real_time_clock_usecs() / 1000; - - next = next * 1103515245 + 12345; - return next; -} - - -bool -iSCSITarget::DiscoverTargets(ip_addr_t address, uint16 port, NodeList* devicesList) -{ - iSCSISession* session = new(nothrow) iSCSISession(); - if (session == NULL) - return false; - status_t error = session->Init(address, port); - if (error != B_OK) { - delete session; - return false; - } - const char* request = "SendTargets=All"; - char* sendTargets = NULL; - size_t sendTargetsLength = 0; - error = session->Connection()->GetText(request, strlen(request) + 1, - &sendTargets, &sendTargetsLength); - session->Close(); - delete session; - if (error != B_OK) { - return false; - } - - bool addedDisk = false; - char* targetName = NULL; - bool seenAddress = false; - for (char* pair = sendTargets; pair < sendTargets + sendTargetsLength; - pair += strlen(pair) + 1) { - printf("%s\n", pair); - if (strncmp(pair, "TargetName=", strlen("TargetName=")) == 0) { - if (targetName != NULL && !seenAddress) { - if (_AddDevice(address, port, targetName, devicesList)) - addedDisk = true; - } - seenAddress = false; - targetName = pair + strlen("TargetName="); - } else if (strncmp(pair, "TargetAddress=", strlen("TargetAddress=")) - == 0) { - seenAddress = true; - char* targetAddress = pair + strlen("TargetAddress="); - char* comma = strrchr(targetAddress, ','); - int addressLength = comma - targetAddress; - targetAddress = strndup(targetAddress, addressLength); - uint16 targetPort = ISCSI_PORT; - char* colon = strrchr(targetAddress, ':'); - if (colon != NULL) { - // colon could be part of an IPv6 address, e.g. [::1.2.3.4] - char* bracket = strrchr(targetAddress, ']'); - if (bracket == NULL || bracket < colon) { - targetPort = strtol(colon + 1, NULL, 10); - colon[0] = '\0'; - } - } - if (targetName != NULL && isdigit(targetAddress[0])) { - if (_AddDevice(ip_parse_address(targetAddress), targetPort, - targetName, devicesList)) - addedDisk = true; - } - free(targetAddress); - } - } - if (targetName != NULL && !seenAddress) { - if (_AddDevice(address, port, targetName, devicesList)) - addedDisk = true; - } - free(sendTargets); - return addedDisk; -} - - -bool -iSCSITarget::_AddDevice(ip_addr_t address, uint16 port, - const char* targetName, NodeList* devicesList) -{ - TRACE("=> %s @ %08lx:%u\n", targetName, address, port); - iSCSITarget* disk = new(nothrow) iSCSITarget(); - if (disk == NULL) - return false; - status_t error = disk->Init(address, port, targetName); - if (error != B_OK) { - delete disk; - return false; - } - TRACE("disk size = %llu\n", disk->Size()); - devicesList->Add(disk); - return true; -} - - -iSCSITarget::iSCSITarget() - : - fSession(NULL), - fTargetName(NULL), - fTargetAlias(NULL) -{ -} - - -iSCSITarget::~iSCSITarget() -{ - free(fTargetName); - free(fTargetAlias); - delete fSession; -} - - -status_t -iSCSITarget::Init(ip_addr_t address, uint16 port, const char* targetName) -{ - fTargetName = strdup(targetName); - if (fTargetName == NULL) - return B_NO_MEMORY; - - fSession = new(nothrow) iSCSISession(fTargetName); - if (fSession == NULL) - return B_NO_MEMORY; - status_t error = fSession->Init(address, port, &fTargetAlias); - if (error != B_OK) - return error; - if (targetName == NULL) - return B_OK; - - error = _GetSize(); - if (error != B_OK) - return error; - - return B_OK; -} - - -status_t -iSCSITarget::_GetSize() -{ - scsi_cmd_read_capacity cmd; - memset(&cmd, 0, sizeof(cmd)); - cmd.opcode = SCSI_OP_READ_CAPACITY; - cmd.relative_address = 0; - cmd.lun = 0; - cmd.lba = 0; - cmd.pmi = 0; - cmd.control = 0; - scsi_res_read_capacity resp; - status_t error = fSession->Connection()->SendCommand(&cmd, sizeof(cmd), - true, false, sizeof(resp), - &resp, 0, sizeof(resp)); - if (error != B_OK) { - TRACE("error %lx sending command!\n", error); - return error; - } - TRACE("lba = %lu, block size = %lu\n", resp.lba, resp.block_size); - fLastLBA = resp.lba; - fBlockSize = resp.block_size; - - return B_OK; -} - - -ssize_t -iSCSITarget::ReadAt(void* /*cookie*/, off_t pos, void* buffer, size_t bufferSize) -{ - TRACE("pos=%llu, size = %lu\n", pos, bufferSize); - - if (fSession == NULL) - return B_NO_INIT; - - if (buffer == NULL || pos < 0 || pos >= Size()) - return B_BAD_VALUE; - if (bufferSize == 0) - return 0; - - uint32 blockOffset = pos % fBlockSize; - - scsi_cmd_rw_16 cmd; - memset(&cmd, 0, sizeof(cmd)); - cmd.opcode = SCSI_OP_READ_16; - cmd.force_unit_access = 0; - cmd.disable_page_out = 0; - cmd.lba = pos / fBlockSize; - cmd.length = (blockOffset + bufferSize + fBlockSize - 1) / fBlockSize; - cmd.control = 0; - status_t error = fSession->Connection()->SendCommand(&cmd, sizeof(cmd), - true, false, cmd.length * fBlockSize, buffer, blockOffset, bufferSize); - if (error != B_OK) { - TRACE("error %lx sending command!\n", error); - return error; - } - - return bufferSize; -} - - -ssize_t -iSCSITarget::WriteAt(void* /*cookie*/, off_t pos, const void* buffer, size_t bufferSize) -{ - return B_PERMISSION_DENIED; -} - - -status_t -iSCSITarget::GetName(char* buffer, size_t bufferSize) const -{ - if (buffer == NULL) - return B_BAD_VALUE; - - snprintf(buffer, bufferSize, "iSCSI:%s", fTargetName); - - return B_OK; -} - - -off_t -iSCSITarget::Size() const -{ - return (fLastLBA + 1) * fBlockSize; -} - - -iSCSISession::iSCSISession(const char* targetName) - : - fDiscovery(targetName == NULL), - fTargetName(targetName), - fConnection(NULL) -{ - fCommandSequenceNumber = _rand(); -} - - -iSCSISession::~iSCSISession() -{ - if (Active()) - Close(); - delete fConnection; -} - - -status_t -iSCSISession::Init(ip_addr_t address, uint16 port, char** targetAlias) -{ - fConnection = new(nothrow) iSCSIConnection(); - if (fConnection == NULL) - return B_NO_MEMORY; - status_t error = fConnection->Init(this); - if (error != B_OK) - return error; - error = fConnection->Open(address, port); - if (error != B_OK) - return error; - error = fConnection->Login(fTargetName, targetAlias); - if (error != B_OK) - return error; - return B_OK; -} - - -status_t -iSCSISession::Close() -{ - if (fConnection == NULL) - return B_NO_INIT; - - status_t error = fConnection->Logout(true); - if (error != B_OK) - return error; - return B_OK; -} - - -iSCSIConnection::iSCSIConnection() - : - fSession(NULL), - fSocket(NULL), - fConnected(false), - fConnectionID(0) -{ -} - - -iSCSIConnection::~iSCSIConnection() -{ - if (fSocket != NULL && fConnected) { - if (Logout() != B_OK) - fSocket->Close(); - } - delete fSocket; -} - - -status_t -iSCSIConnection::Init(iSCSISession* session) -{ - fSession = session; - return B_OK; -} - -status_t -iSCSIConnection::Open(ip_addr_t address, uint16 port) -{ - fSocket = new(nothrow) TCPSocket(); - if (fSocket == NULL) - return B_NO_MEMORY; - TRACE("connecting to target...\n"); - status_t error = fSocket->Connect(address, port); - if (error != B_OK) - return error; - fConnected = true; - TRACE("connected.\n"); - fConnectionID = _rand(); - return B_OK; -} - - -status_t -iSCSIConnection::Login(const char* targetName, char** targetAlias) -{ - char data[256]; - size_t dataLength = 0; - const char* keyValue; - keyValue = "InitiatorName=iqn.2002-10.org.haiku-os:haiku.bootloader.hostX"; - strcpy(data + dataLength, keyValue); - dataLength += strlen(keyValue) + 1; - if (targetName != NULL) { - dataLength += sprintf(data + dataLength, "TargetName=%s", targetName) + 1; - } else { - keyValue = "SessionType=Discovery"; - strcpy(data + dataLength, keyValue); - dataLength += strlen(keyValue) + 1; - } - - iscsi_login_request req; - req.transit = true; - req.c = false; - req.currentStage = ISCSI_SESSION_STAGE_LOGIN_OPERATIONAL_NEGOTIATION; - req.nextStage = ISCSI_SESSION_STAGE_FULL_FEATURE_PHASE; - req.versionMax = ISCSI_VERSION; - req.versionMin = ISCSI_VERSION; - req.totalAHSLength = 0; - req.dataSegmentLength = dataLength; - TRACE("data segment length = %lu\n", req.dataSegmentLength); - req.isid.t = ISCSI_ISID_RANDOM; - req.isid.a = 0; - uint32 random = _rand(); - req.isid.b = random >> 8; - req.isid.c = random & 0xff; - req.isid.d = _rand(); - req.tsih = 0; - req.initiatorTaskTag = _rand(); - req.cid = fConnectionID; - req.cmdSN = fSession->CommandSequenceNumber(); - req.expStatSN = 0; - status_t error = fSocket->Write(&req, sizeof(req)); - if (error != B_OK) { - return error; - } - for (unsigned int i = dataLength; i < ISCSI_ALIGN(dataLength); i++) - data[i] = '\0'; - dataLength = ISCSI_ALIGN(dataLength); - TRACE("data length = %lu\n", dataLength); - error = fSocket->Write(data, dataLength); - if (error != B_OK) { - TRACE("write error\n"); - return error; - } - TRACE("request sent.\n"); - - iscsi_login_response resp; - size_t bytesRead = 0; - error = fSocket->Read(&resp, sizeof(resp), &bytesRead, 10000000LL); - if (error != B_OK) { - TRACE("response read error\n"); - return error; - } - TRACE("bytesRead = %lu\n", bytesRead); - TRACE("response: opcode = %x, status class = %u, status detail = %u, transit = %u, data length = %lu\n", - resp.opcode, resp.statusClass, resp.statusDetail, resp.transit, resp.dataSegmentLength); - if (resp.dataSegmentLength > 0) { - error = fSocket->Read(data, resp.dataSegmentLength, &bytesRead, 1000000LL); - if (error != B_OK) { - TRACE("response data read error\n"); - return error; - } - TRACE("bytesRead = %lu\n", bytesRead); - if (resp.dataSegmentLength % ISCSI_ALIGNMENT) { - error = fSocket->Read(NULL, ISCSI_PADDING(resp.dataSegmentLength), &bytesRead, 100000LL); - if (error != B_OK) { - TRACE("response padding read error\n"); - return error; - } - TRACE("bytesRead = %lu\n", bytesRead); - } - for (char* pair = data; pair < data + resp.dataSegmentLength; pair += strlen(pair) + 1) { - TRACE("%s\n", pair); - if (targetAlias != NULL && strncmp(pair, "TargetAlias=", strlen("TargetAlias=")) == 0) { - *targetAlias = strdup(pair + strlen("TargetAlias=")); - } - } - } - fStatusSequenceNumber = resp.statSN; - if (resp.statusClass != 0) { - TRACE("response indicates failure.\n"); - return B_BAD_VALUE; - } - return B_OK; -} - - -status_t -iSCSIConnection::Logout(bool closeSession) -{ - iscsi_logout_request req; - TRACE("req size = %lu\n", sizeof(req)); - req.immediateDelivery = true; - req.reasonCode = closeSession ? ISCSI_LOGOUT_REASON_CLOSE_SESSION - : ISCSI_LOGOUT_REASON_CLOSE_CONNECTION; - req.totalAHSLength = 0; - req.dataSegmentLength = 0; - req.initiatorTaskTag = _rand(); - req.cid = closeSession ? 0 : fConnectionID; - req.cmdSN = fSession->CommandSequenceNumber(); - req.expStatSN = fStatusSequenceNumber; - status_t error = fSocket->Write(&req, sizeof(req)); - if (error != B_OK) { - TRACE("request write error\n"); - return error; - } - - iscsi_logout_response resp; - TRACE("resp size = %lu\n", sizeof(resp)); - size_t bytesRead = 0; - error = fSocket->Read(&resp, sizeof(resp), &bytesRead, 10000000LL); - if (error != B_OK) { - TRACE("response read error\n"); - return error; - } - TRACE("bytesRead = %lu\n", bytesRead); - TRACE("response: opcode = %x, response = %u\n", - resp.opcode, resp.response); - fStatusSequenceNumber = resp.statSN; - if (resp.response != 0) { - TRACE("response indicates failure.\n"); - return B_ERROR; - } - - fSocket->Close(); - fConnected = false; - return B_OK; -} - - -status_t -iSCSIConnection::GetText(const char* request, size_t requestLength, char** response, size_t* responseLength) -{ - iscsi_text_request req; - req.immediateDelivery = true; - req.final = true; - req.c = false; - req.totalAHSLength = 0; - req.dataSegmentLength = requestLength; - req.lun = 0; - req.initiatorTaskTag = _rand(); - req.targetTransferTag = 0xffffffffL; - req.cmdSN = fSession->NextCommandSequenceNumber(); - req.expStatSN = fStatusSequenceNumber; - status_t error = fSocket->Write(&req, sizeof(req)); - if (error != B_OK) { - TRACE("iSCSI text request write error\n"); - return error; - } - error = fSocket->Write(request, requestLength); - if (error != B_OK) { - TRACE("iSCSI text request data write error\n"); - return error; - } - if (requestLength % ISCSI_ALIGNMENT != 0) { - char buffer[3]; - memset(buffer, 0, 3); - error = fSocket->Write(buffer, ISCSI_ALIGNMENT - (requestLength % ISCSI_ALIGNMENT)); - if (error != B_OK) { - TRACE("iSCSI text request padding write error\n"); - return error; - } - } - - iscsi_logout_response resp; - size_t bytesRead = 0; - error = fSocket->Read(&resp, sizeof(resp), &bytesRead, 10000000LL); - if (error != B_OK) { - TRACE("response read error\n"); - return error; - } - TRACE("bytesRead = %lu\n", bytesRead); - TRACE("response: opcode = %x\n", - resp.opcode); - *response = (char*)malloc(resp.dataSegmentLength); - if (*response == NULL) - return B_NO_MEMORY; - error = fSocket->Read(*response, resp.dataSegmentLength, &bytesRead, 10000000LL); - if (error != B_OK) { - TRACE("response read error\n"); - return error; - } - TRACE("bytesRead = %lu\n", bytesRead); - *responseLength = resp.dataSegmentLength; - if ((resp.dataSegmentLength % ISCSI_ALIGNMENT) != 0) { - error = fSocket->Read(NULL, ISCSI_PADDING(resp.dataSegmentLength), &bytesRead, 1000000LL); - if (error != B_OK) { - TRACE("response padding read error\n"); - return error; - } - } - fStatusSequenceNumber = resp.statSN; - if (resp.opcode != ISCSI_OPCODE_TEXT_RESPONSE) { - PANIC("response opcode unexpected!"); - return B_ERROR; - } - - return B_OK; -} - - -status_t -iSCSIConnection::SendCommand(const void* command, size_t commandSize, - bool r, bool w, uint32 expectedDataTransferLength, - void* response, uint32 responseOffset, size_t responseLength) -{ - TRACE("command size = %lu, offset = %lu, length = %lu\n", commandSize, responseOffset, responseLength); - iscsi_scsi_command req; - req.immediateDelivery = true; - req.final = true; - req.r = r; - req.w = w; - req.attr = 0; - req.totalAHSLength = 0; - req.dataSegmentLength = (commandSize > 16) ? commandSize - 16 : 0; - req.lun = 0; - req.initiatorTaskTag = _rand(); - req.expectedDataTransferLength = expectedDataTransferLength; - req.cmdSN = fSession->NextCommandSequenceNumber(); - req.expStatSN = fStatusSequenceNumber; - if (commandSize < 16) - memset(req.cdb, 0, 16); - memcpy(req.cdb, command, commandSize <= 16 ? commandSize : 16); - status_t error = fSocket->Write(&req, sizeof(req)); - if (error != B_OK) { - TRACE("write error\n"); - return error; - } - if (commandSize > 16) { - error = fSocket->Write((uint8*)command + 16, commandSize - 16); - if (error != B_OK) { - TRACE("write error\n"); - return error; - } - if ((req.dataSegmentLength % ISCSI_ALIGNMENT) != 0) { - char buffer[3]; - memset(buffer, 0, 3); - error = fSocket->Write(buffer, ISCSI_ALIGNMENT - (req.dataSegmentLength % ISCSI_ALIGNMENT)); - if (error != B_OK) { - TRACE("request padding write error\n"); - return error; - } - } - } - - struct iscsi_basic_header_segment resp; - error = _ReadResponse(&resp); - if (error != B_OK) { - TRACE("response read error\n"); - return error; - } - while (r && resp.opcode != ISCSI_OPCODE_SCSI_RESPONSE) { - if (resp.opcode != ISCSI_OPCODE_SCSI_DATA_IN) - PANIC("response opcode %x unexpected\n", resp.opcode); - iscsi_scsi_data_in* dataIn = (iscsi_scsi_data_in*)&resp; - TRACE("A=%u, S=%u, bufferOffset=%lu, length = %lu\n", dataIn->acknowledge, dataIn->S, dataIn->bufferOffset, resp.dataSegmentLength); - if (resp.dataSegmentLength > 0) { - size_t toRead = resp.dataSegmentLength; - size_t toSkip = 0; - if (dataIn->bufferOffset < responseOffset) { - toSkip = MIN(responseOffset - dataIn->bufferOffset, resp.dataSegmentLength); - error = _Read(NULL, toSkip); - if (error != B_OK) { - TRACE("response skip error\n"); - return error; - } - TRACE("skipped %lu response bytes\n", toSkip); - toRead -= toSkip; - } - if (toRead > 0) { - if (dataIn->bufferOffset + resp.dataSegmentLength > responseOffset + responseLength) { - size_t cutOff = expectedDataTransferLength - (responseOffset + responseLength); - toRead = MIN(expectedDataTransferLength - cutOff - dataIn->bufferOffset, resp.dataSegmentLength) - toSkip; - } - error = _Read((uint8*)response + dataIn->bufferOffset - responseOffset, toRead); - if (error != B_OK) { - TRACE("response read error: %lx\n", error); - return error; - } - } - size_t toCutOff = resp.dataSegmentLength - toSkip - toRead; - if (toCutOff > 0) { - error = _Read(NULL, toCutOff); - if (error != B_OK) { - TRACE("response cut-off error\n"); - return error; - } - } - if (toSkip + toRead + toCutOff != resp.dataSegmentLength) - PANIC("inconcistency while reading detected!\n"); - } - if ((resp.dataSegmentLength % ISCSI_ALIGNMENT) != 0) { - error = _Read(NULL, ISCSI_PADDING(resp.dataSegmentLength)); - if (error != B_OK) { - TRACE("response padding read error\n"); - return error; - } - } - fStatusSequenceNumber = dataIn->statSN; - if (dataIn->S) { - // TODO check status - return B_OK; - } - - error = _ReadResponse(&resp); - if (error != B_OK) { - TRACE("response read error\n"); - return error; - } - } - - TRACE("response: opcode = %x, AHS length = %x, data length = %lu\n", - resp.opcode, resp.totalAHSLength, resp.dataSegmentLength); - if (resp.opcode != ISCSI_OPCODE_SCSI_RESPONSE) { - PANIC("response opcode unexpected!\n"); - return B_ERROR; - } - iscsi_scsi_response* scsiResp = (iscsi_scsi_response*)&resp; - TRACE("response: response = %x, status = %x, SNACK=%x\n", - scsiResp->response, scsiResp->status, scsiResp->snackTag); - if (resp.dataSegmentLength > 0) { - void* buffer = NULL; - if (scsiResp->status != SCSI_STATUS_GOOD) - buffer = malloc(resp.dataSegmentLength); - error = _Read(buffer, resp.dataSegmentLength); - if (error != B_OK) { - TRACE("response read error\n"); - return error; - } -#ifdef TRACE_ISCSI - if (scsiResp->status != SCSI_STATUS_GOOD) { - scsi_sense* sense = (scsi_sense*)((uint16*)buffer + 1); - TRACE("error code = %u, sense key = %u, ILI = %u, asc = %x\n", - sense->error_code, sense->sense_key, sense->ILI, (sense->asc << 8) | sense->ascq); - } -#endif - free(buffer); - } - if ((resp.dataSegmentLength % ISCSI_ALIGNMENT) != 0) { - error = _Read(NULL, ISCSI_PADDING(resp.dataSegmentLength)); - if (error != B_OK) { - TRACE("response padding read error\n"); - return error; - } - } - fStatusSequenceNumber = scsiResp->statSN; - if (scsiResp->response != 0x00 || scsiResp->status != SCSI_STATUS_GOOD) - return B_BAD_VALUE; - - return B_OK; -} - - -status_t -iSCSIConnection::_ReadResponse(iscsi_basic_header_segment* resp, bigtime_t timeout) -{ - if (resp == NULL) - return B_BAD_VALUE; - - status_t error = _Read(resp, sizeof(iscsi_basic_header_segment), timeout); - if (error != B_OK) { - TRACE("initial read failed\n"); - return error; - } - - if (resp->reserved == true) { - TRACE("reserved bit is 1!\n"); - return B_IO_ERROR; - } - // theoretically process header checksum here, if available - - // At any time a target can send a NOP-In, requiring us to answer with a NOP-Out. - // TODO handle asynchronous event message - while (resp->opcode == ISCSI_OPCODE_NOP_IN) { - iscsi_nop_in* nopIn = (iscsi_nop_in*)resp; - // A NOP-In can also be the answer to our own NOP-Out though. - if (nopIn->targetTransferTag == 0xffffffff) - return B_OK; - TRACE("received NOP-In (ping data length = %lu)\n", nopIn->dataSegmentLength); - void* pingData = NULL; - if (nopIn->dataSegmentLength > 0) { - pingData = malloc(nopIn->dataSegmentLength); - if (pingData == NULL) - return B_NO_MEMORY; - error = _Read(pingData, nopIn->dataSegmentLength, timeout); - if (error != B_OK) { - TRACE("NOP-In ping data read error\n"); - free(pingData); - return error; - } - } - if ((nopIn->dataSegmentLength % ISCSI_ALIGNMENT) != 0) { - error = _Read(NULL, ISCSI_PADDING(nopIn->dataSegmentLength), timeout); - if (error != B_OK) { - TRACE("NOP-In padding read error\n"); - free(pingData); - return error; - } - } - iscsi_nop_out nopOut; - nopOut.totalAHSLength = 0; - nopOut.dataSegmentLength = nopIn->dataSegmentLength; - nopOut.lun = nopIn->lun; - nopOut.initiatorTaskTag = 0xffffffff; - nopOut.targetTransferTag = nopIn->targetTransferTag; - nopOut.cmdSN = fSession->NextCommandSequenceNumber(); - nopOut.expStatSN = fStatusSequenceNumber; - error = fSocket->Write(&nopOut, sizeof(nopOut)); - if (error != B_OK) { - TRACE("NOP-Out write error\n"); - free(pingData); - return error; - } - if (nopOut.dataSegmentLength > 0) { - error = fSocket->Write(pingData, nopOut.dataSegmentLength); - free(pingData); - if (error != B_OK) { - TRACE("NOP-Out ping data write error\n"); - return error; - } - if ((nopOut.dataSegmentLength % ISCSI_ALIGNMENT) != 0) { - char buffer[3]; - memset(buffer, 0, 3); - error = fSocket->Write(buffer, ISCSI_ALIGNMENT - (nopOut.dataSegmentLength % ISCSI_ALIGNMENT)); - if (error != B_OK) { - TRACE("NOP-Out padding write error\n"); - return error; - } - } - } - - error = _Read(resp, sizeof(iscsi_basic_header_segment), timeout); - if (error != B_OK) { - TRACE("read failed\n"); - return error; - } - } - - return B_OK; -} - - -status_t -iSCSIConnection::_Read(void* buffer, size_t bufferSize, bigtime_t timeout) -{ - size_t bytesRead; - status_t error = fSocket->Read(buffer, bufferSize, &bytesRead, timeout); - if (error != B_OK) - return error; - if (bytesRead < bufferSize) { - dprintf("not enough data available: %lu vs. %lu\n", bytesRead, bufferSize); - return B_ERROR; - } - return B_OK; -} diff --git a/src/system/boot/platform/openfirmware/devices.cpp b/src/system/boot/platform/openfirmware/devices.cpp index 240b0581cc..f123149980 100644 --- a/src/system/boot/platform/openfirmware/devices.cpp +++ b/src/system/boot/platform/openfirmware/devices.cpp @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include @@ -76,21 +75,13 @@ platform_add_boot_device(struct stage2_args *args, NodeList *devicesList) } } - // init a remote disk, if possible + // init a native remote disk, if possible RemoteDisk *remoteDisk = RemoteDisk::FindAnyRemoteDisk(); if (remoteDisk != NULL) { 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; }