Skip to content

Commit

Permalink
[driver] Add sBFT detection and debug parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
Michael Brown committed Oct 23, 2009
1 parent f8f35a3 commit 8f4e2db
Show file tree
Hide file tree
Showing 8 changed files with 321 additions and 10 deletions.
Binary file modified bin/amd64/sanbootconf.sys
Binary file not shown.
Binary file modified bin/amd64/setup.exe
Binary file not shown.
Binary file modified bin/i386/sanbootconf.sys
Binary file not shown.
Binary file modified bin/i386/setup.exe
Binary file not shown.
59 changes: 50 additions & 9 deletions driver/sanbootconf.c
Expand Up @@ -22,11 +22,14 @@
#include "sanbootconf.h"
#include "acpi.h"
#include "ibft.h"
#include "sbft.h"

/** Device private data */
typedef struct _SANBOOTCONF_PRIV {
/* Copy of iBFT */
/* Copy of iBFT, if any */
PIBFT_TABLE ibft;
/* Copy of sBFT, if any */
PSBFT_TABLE sbft;
} SANBOOTCONF_PRIV, *PSANBOOTCONF_PRIV;

/** Unique GUID for IoCreateDeviceSecure() */
Expand All @@ -35,7 +38,13 @@ DEFINE_GUID ( GUID_SANBOOTCONF_CLASS, 0x8a2f8602, 0x8f0b, 0x4138,

/** IoControl code to retrieve iBFT */
#define IOCTL_SANBOOTCONF_IBFT \
CTL_CODE ( FILE_DEVICE_UNKNOWN, 1, METHOD_BUFFERED, FILE_READ_ACCESS )
CTL_CODE ( FILE_DEVICE_UNKNOWN, 0x0001, METHOD_BUFFERED, \
FILE_READ_ACCESS )

/** IoControl code to retrieve sBFT */
#define IOCTL_SANBOOTCONF_SBFT \
CTL_CODE ( FILE_DEVICE_UNKNOWN, 0x0873, METHOD_BUFFERED, \
FILE_READ_ACCESS )

/** Device name */
static const WCHAR sanbootconf_device_name[] = L"\\Device\\sanbootconf";
Expand Down Expand Up @@ -79,11 +88,29 @@ static NTSTATUS sanbootconf_iocontrol_irp ( PDEVICE_OBJECT device, PIRP irp ) {
switch ( irpsp->Parameters.DeviceIoControl.IoControlCode ) {
case IOCTL_SANBOOTCONF_IBFT:
DbgPrint ( "iBFT requested\n" );
if ( len > priv->ibft->acpi.length )
len = priv->ibft->acpi.length;
RtlCopyMemory ( irp->AssociatedIrp.SystemBuffer,
priv->ibft, len );
status = STATUS_SUCCESS;
if ( priv->ibft ) {
if ( len > priv->ibft->acpi.length )
len = priv->ibft->acpi.length;
RtlCopyMemory ( irp->AssociatedIrp.SystemBuffer,
priv->ibft, len );
status = STATUS_SUCCESS;
} else {
DbgPrint ( "No iBFT available!\n" );
status = STATUS_NO_SUCH_FILE;
}
break;
case IOCTL_SANBOOTCONF_SBFT:
DbgPrint ( "sBFT requested\n" );
if ( priv->sbft ) {
if ( len > priv->sbft->acpi.length )
len = priv->sbft->acpi.length;
RtlCopyMemory ( irp->AssociatedIrp.SystemBuffer,
priv->sbft, len );
status = STATUS_SUCCESS;
} else {
DbgPrint ( "No sbft available!\n" );
status = STATUS_NO_SUCH_FILE;
}
break;
default:
DbgPrint ( "Unrecognised IoControl %x\n",
Expand All @@ -108,12 +135,13 @@ static NTSTATUS create_sanbootconf_device ( PDRIVER_OBJECT driver,
PDEVICE_OBJECT *device ) {
UNICODE_STRING u_device_name;
UNICODE_STRING u_device_symlink;
unsigned int i;
PSANBOOTCONF_PRIV priv;
ULONG i;
NTSTATUS status;

/* Create device */
RtlInitUnicodeString ( &u_device_name, sanbootconf_device_name );
status = IoCreateDeviceSecure ( driver, sizeof ( SANBOOTCONF_PRIV ),
status = IoCreateDeviceSecure ( driver, sizeof ( *priv ),
&u_device_name, FILE_DEVICE_UNKNOWN,
FILE_DEVICE_SECURE_OPEN, FALSE,
&SDDL_DEVOBJ_SYS_ALL_ADM_ALL,
Expand All @@ -123,6 +151,8 @@ static NTSTATUS create_sanbootconf_device ( PDRIVER_OBJECT driver,
sanbootconf_device_name, status );
return status;
}
priv = (*device)->DeviceExtension;
RtlZeroMemory ( priv, sizeof ( *priv ) );
(*device)->Flags &= ~DO_DEVICE_INITIALIZING;

/* Create device symlinks */
Expand Down Expand Up @@ -183,6 +213,17 @@ NTSTATUS DriverEntry ( IN PDRIVER_OBJECT DriverObject,
status = STATUS_SUCCESS;
}

/* Look for an sBFT */
status = find_acpi_table ( SBFT_SIG, &table );
if ( NT_SUCCESS ( status ) ) {
priv->sbft = ( ( PSBFT_TABLE ) table );
parse_sbft ( priv->sbft );
} else {
/* Lack of an sBFT is not necessarily an error */
DbgPrint ( "No sBFT found\n" );
status = STATUS_SUCCESS;
}

DbgPrint ( "SAN Boot Configuration Driver initialisation complete\n" );

err_create_sanbootconf_device:
Expand Down
126 changes: 126 additions & 0 deletions driver/sbft.c
@@ -0,0 +1,126 @@
/*
* Copyright (C) 2009 Fen Systems Ltd <mbrown@fensystems.co.uk>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include <ntddk.h>
#include <ntstrsafe.h>
#include "sanbootconf.h"
#include "sbft.h"

/**
* Parse sBFT SCSI subtable
*
* @v sbft sBFT
* @v scsi SCSI subtable
*/
static VOID parse_sbft_scsi ( PSBFT_TABLE sbft, PSBFT_SCSI_SUBTABLE scsi ) {

DbgPrint ( "Found sBFT SCSI subtable:\n" );
DbgPrint ( " LUN = %04x-%04x-%04x-%04x\n",
( ( scsi->lun >> 48 ) & 0xffff ),
( ( scsi->lun >> 32 ) & 0xffff ),
( ( scsi->lun >> 16 ) & 0xffff ),
( ( scsi->lun >> 0 ) & 0xffff ) );
( VOID ) sbft;
}

/**
* Parse sBFT SRP subtable
*
* @v sbft sBFT
* @v srp SRP subtable
*/
static VOID parse_sbft_srp ( PSBFT_TABLE sbft, PSBFT_SRP_SUBTABLE srp ) {

DbgPrint ( "Found sBFT SRP subtable:\n" );
DbgPrint ( " Initiator port ID = 0x%08x%08x%08x%08x\n",
RtlUlongByteSwap ( srp->initiator_port_id.u.dwords[0] ),
RtlUlongByteSwap ( srp->initiator_port_id.u.dwords[1] ),
RtlUlongByteSwap ( srp->initiator_port_id.u.dwords[2] ),
RtlUlongByteSwap ( srp->initiator_port_id.u.dwords[3] ) );
DbgPrint ( " Target port ID = 0x%08x%08x%08x%08x\n",
RtlUlongByteSwap ( srp->target_port_id.u.dwords[0] ),
RtlUlongByteSwap ( srp->target_port_id.u.dwords[1] ),
RtlUlongByteSwap ( srp->target_port_id.u.dwords[2] ),
RtlUlongByteSwap ( srp->target_port_id.u.dwords[3] ) );
( VOID ) sbft;
}

/**
* Parse sBFT IB subtable
*
* @v sbft sBFT
* @v ib IB subtable
*/
static VOID parse_sbft_ib ( PSBFT_TABLE sbft, PSBFT_IB_SUBTABLE ib ) {

DbgPrint ( "Found sBFT IB subtable:\n" );
DbgPrint ( " Source GID = 0x%08x%08x%08x%08x\n",
RtlUlongByteSwap ( ib->sgid.u.dwords[0] ),
RtlUlongByteSwap ( ib->sgid.u.dwords[1] ),
RtlUlongByteSwap ( ib->sgid.u.dwords[2] ),
RtlUlongByteSwap ( ib->sgid.u.dwords[3] ) );
DbgPrint ( " Destination GID = 0x%08x%08x%08x%08x\n",
RtlUlongByteSwap ( ib->dgid.u.dwords[0] ),
RtlUlongByteSwap ( ib->dgid.u.dwords[1] ),
RtlUlongByteSwap ( ib->dgid.u.dwords[2] ),
RtlUlongByteSwap ( ib->dgid.u.dwords[3] ) );
DbgPrint ( " Service ID = 0x%08x%08x\n",
RtlUlongByteSwap ( ib->service_id.u.dwords[0] ),
RtlUlongByteSwap ( ib->service_id.u.dwords[1] ) );
DbgPrint ( " Partition key = 0x%04x\n", ib->pkey );
( VOID ) sbft;
}

/**
* Parse sBFT
*
* @v sbft sBFT
*/
VOID parse_sbft ( PSBFT_TABLE sbft ) {
PSBFT_SCSI_SUBTABLE scsi;
PSBFT_SRP_SUBTABLE srp;
PSBFT_IB_SUBTABLE ib;

if ( sbft->scsi_offset ) {
scsi = ( ( PSBFT_SCSI_SUBTABLE )
( ( PUCHAR ) sbft + sbft->scsi_offset ) );
parse_sbft_scsi ( sbft, scsi );
}
if ( sbft->srp_offset ) {
srp = ( ( PSBFT_SRP_SUBTABLE )
( ( PUCHAR ) sbft + sbft->srp_offset ) );
parse_sbft_srp ( sbft, srp );
}
if ( sbft->ib_offset ) {
ib = ( ( PSBFT_IB_SUBTABLE )
( ( PUCHAR ) sbft + sbft->ib_offset ) );
parse_sbft_ib ( sbft, ib );
}
}
144 changes: 144 additions & 0 deletions driver/sbft.h
@@ -0,0 +1,144 @@
#ifndef _SBFT_H
#define _SBFT_H

/*
* Copyright (C) 2009 Fen Systems Ltd <mbrown@fensystems.co.uk>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/

/** @file
*
* SRP boot firmware table
*
* The working draft specification for the SRP boot firmware table can
* be found at
*
* http://etherboot.org/wiki/srp/sbft
*
*/

#include "acpi.h"

/** SRP Boot Firmware Table signature */
#define SBFT_SIG "sBFT"

/**
* SRP Boot Firmware Table
*/
#pragma pack(1)
typedef struct _SBFT_TABLE {
/** ACPI header */
ACPI_DESCRIPTION_HEADER acpi;
/** Offset to SCSI subtable */
USHORT scsi_offset;
/** Offset to SRP subtable */
USHORT srp_offset;
/** Offset to IB subtable, if present */
USHORT ib_offset;
/** Reserved */
UCHAR reserved[6];
} SBFT_TABLE, *PSBFT_TABLE;
#pragma pack()

/**
* sBFT SCSI subtable
*/
#pragma pack(1)
typedef struct _SBFT_SCSI_SUBTABLE {
/** LUN */
ULONGLONG lun;
} SBFT_SCSI_SUBTABLE, *PSBFT_SCSI_SUBTABLE;
#pragma pack()

/** An SRP port ID */
#pragma pack(1)
typedef struct _SRP_PORT_ID {
union {
UCHAR bytes[16];
USHORT words[8];
ULONG dwords[4];
} u;
} SRP_PORT_ID, *PSRP_PORT_ID;
#pragma pack()

/**
* sBFT SRP subtable
*/
#pragma pack(1)
typedef struct _SBFT_SRP_SUBTABLE {
/** Initiator port identifier */
SRP_PORT_ID initiator_port_id;
/** Target port identifier */
SRP_PORT_ID target_port_id;
} SBFT_SRP_SUBTABLE, *PSBFT_SRP_SUBTABLE;
#pragma pack()

/** An Infiniband GUID */
#pragma pack(1)
typedef struct _IB_GUID {
union {
UCHAR bytes[8];
USHORT words[4];
ULONG dwords[2];
} u;
} IB_GUID, *PIB_GUID;
#pragma pack()

/** An Infiniband GID */
#pragma pack(1)
typedef struct _IB_GID {
union {
UCHAR bytes[16];
USHORT words[8];
ULONG dwords[4];
IB_GUID guid[2];
} u;
} IB_GID, *PIB_GID;
#pragma pack()

/**
* sBFT IB subtable
*/
#pragma pack(1)
typedef struct _SBFT_IB_SUBTABLE {
/** Source GID */
IB_GID sgid;
/** Destination GID */
IB_GID dgid;
/** Service ID */
IB_GUID service_id;
/** Partition key */
USHORT pkey;
/** Reserved */
UCHAR reserved[6];
} SBFT_IB_SUBTABLE, *PSBFT_IB_SUBTABLE;
#pragma pack()

extern VOID parse_sbft ( PSBFT_TABLE sbft );

#endif /* _SBFT_H */
2 changes: 1 addition & 1 deletion driver/sources
Expand Up @@ -8,4 +8,4 @@ TARGETLIBS = $(DDK_LIB_PATH)\ndis.lib $(DDK_LIB_PATH)\ntstrsafe.lib $(DDK_LIB_PA

MSC_WARNING_LEVEL = /W4 /Wp64 /WX

SOURCES = sanbootconf.c registry.c acpi.c ibft.c
SOURCES = sanbootconf.c registry.c acpi.c ibft.c sbft.c

0 comments on commit 8f4e2db

Please sign in to comment.