NT4/private/ntos/fw/alpha/omf.c
2020-09-30 17:12:29 +02:00

3795 lines
88 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// ----------------------------------------------------------------------------
//
// Copyright (c) 1992 Olivetti
//
// File: omf.c
//
// Description: this code implements the omf protocol as defined
// in the ARC-EISA addendum.
//
// ----------------------------------------------------------------------------
#include "fwp.h"
#include "oli2msft.h"
#include "arceisa.h"
#include "inc.h"
#include "string.h"
#include "debug.h"
extern BL_FILE_TABLE BlFileTable [BL_FILE_TABLE_SIZE];
#define DEVICE_DEVICE 0xDEAD
// ----------------------------------------------------------------------------
// Declare Function Prototypes
// ----------------------------------------------------------------------------
ARC_STATUS
OmfOpen
(
IN PCHAR OpenPath,
IN OPEN_MODE OpenMode,
IN OUT PULONG FileId
);
ARC_STATUS
OmfClose
(
IN ULONG FileId
);
ARC_STATUS
OmfMount
(
IN PCHAR MountPath,
IN MOUNT_OPERATION Operation
);
ARC_STATUS
OmfRead
(
IN ULONG FileId,
IN PVOID Buffer,
IN ULONG Length,
OUT PULONG Count
);
ARC_STATUS
OmfWrite
(
IN ULONG FileId,
IN PVOID Buffer,
IN ULONG Length,
OUT PULONG Count
);
ARC_STATUS
OmfGetReadStatus
(
IN ULONG FileId
);
ARC_STATUS
OmfSeek
(
IN ULONG FileId,
IN PLARGE_INTEGER Offset,
IN SEEK_MODE SeekMode
);
ARC_STATUS
OmfGetFileInformation
(
IN ULONG FileId,
OUT PFILE_INFORMATION Buffer
);
ARC_STATUS
OmfSetFileInformation
(
IN ULONG FileId,
IN ULONG AttributeFlags,
IN ULONG AttributeMask
);
ARC_STATUS
OmfGetDirectoryEntry
(
IN ULONG FileId,
IN DIRECTORY_ENTRY *DirEntry,
IN ULONG NumberDir,
OUT PULONG CountDir
);
ARC_STATUS
OmfFileOpen
(
IN PCHAR OpenPath,
IN OPEN_MODE OpenMode,
IN OUT PULONG FileId
);
ARC_STATUS
OmfFileClose
(
IN ULONG FileId
);
ARC_STATUS
OmfFileMount
(
IN PCHAR MountPath,
IN MOUNT_OPERATION Operation
);
ARC_STATUS
OmfFileRead
(
IN ULONG FileId,
IN PVOID Buffer,
IN ULONG Length,
OUT PULONG Count
);
ARC_STATUS
OmfFileWrite
(
IN ULONG FileId,
IN PVOID Buffer,
IN ULONG Length,
OUT PULONG Count
);
ARC_STATUS
OmfFileGetReadStatus
(
IN ULONG FileId
);
ARC_STATUS
OmfFileSeek
(
IN ULONG FileId,
IN PLARGE_INTEGER Offset,
IN SEEK_MODE SeekMode
);
ARC_STATUS
OmfFileGetFileInformation
(
IN ULONG FileId,
OUT PFILE_INFORMATION Buffer
);
ARC_STATUS
OmfFileSetFileInformation
(
IN ULONG FileId,
IN ULONG AttributeFlags,
IN ULONG AttributeMask
);
ARC_STATUS
OmfFileGetDirectoryEntry
(
IN ULONG FileId,
IN DIRECTORY_ENTRY *DirEntry,
IN ULONG NumberDir,
OUT PULONG CountDir
);
BOOLEAN
MaxOmfFatFiles
(
IN OUT PCHAR MasterName,
IN PCHAR CheckedName
);
BOOLEAN
OmfFileNameValidate
(
IN PCHAR OpenPath,
OUT PCHAR OmfFileName,
OUT PCHAR OmfType
);
BOOLEAN
CmpOmfFiles
(
IN PCHAR OmfFileName,
IN CHAR OmfType,
IN POMF_DIR_ENT POmfDirEnt
);
BOOLEAN
OmfHeaderValidate
(
IN ULONG FileId
);
BOOLEAN
OmfFileValidate
(
IN ULONG FileId
);
VOID
ConvertOmfDirToArcDir
(
IN POMF_DIR_ENT POmfDirEnt,
OUT DIRECTORY_ENTRY *PArcDirEnt
);
BOOLEAN
FwGetEisaId
(
IN PCHAR PathName,
OUT PCHAR EisaId,
OUT PUCHAR IdInfo
);
VOID
FwUncompressEisaId
(
IN PUCHAR CompEisaId,
OUT PUCHAR UncompEisaId
);
BOOLEAN
FwGetEisaBusIoCpuAddress
(
IN PCHAR EisaPath,
OUT PVOID *IoBusAddress
);
PCHAR
FwGetEnvironmentVariable
(
IN PCHAR Variable
);
PCONFIGURATION_COMPONENT
FwGetComponent
(
IN PCHAR Pathname
);
LARGE_INTEGER
RtlConvertUlongToLargeInteger
(
IN ULONG UnsignedInteger
);
LARGE_INTEGER
RtlLargeIntegerAdd
(
IN LARGE_INTEGER Addend1,
IN LARGE_INTEGER Addend2
);
ARC_STATUS
FwFileIdChecksum
(
IN ULONG FileId,
IN LARGE_INTEGER StartingOffset,
IN ULONG Length,
IN OUT PUCHAR Checksum
);
BOOLEAN
FwGetMnemonicKey
(
IN PCHAR Path,
IN PCHAR Mnemonic,
IN PULONG Key
);
BOOLEAN
FwGetNextMnemonic
(
IN PCHAR Path,
IN PCHAR Mnemonic,
OUT PCHAR NextMnemonic
);
BOOLEAN
FwGetMnemonicPath
(
IN PCHAR Path,
IN PCHAR Mnemonic,
OUT PCHAR MnemonicPath
);
BOOLEAN
GetNextPath
(
IN OUT PCHAR *PPathList,
OUT PCHAR PathTarget
);
// ----------------------------------------------------------------------------
// Global Data
// ----------------------------------------------------------------------------
//
// Omf entry table.
// This is a structure that provides entry to the OMF system procedures.
// It is exported when a OMF is opened as a device.
//
BL_DEVICE_ENTRY_TABLE OmfEntryTable =
{
OmfClose,
OmfMount,
OmfOpen,
OmfRead,
OmfGetReadStatus,
OmfSeek,
OmfWrite,
OmfGetFileInformation,
OmfSetFileInformation,
NULL,
OmfGetDirectoryEntry
};
//
// Omf file entry table.
// This is a structure that provides entry to the OMF file system procedures.
// It is exported when a OMF file is opened.
//
BL_DEVICE_ENTRY_TABLE OmfFileEntryTable =
{
OmfFileClose,
OmfFileMount,
OmfFileOpen,
OmfFileRead,
OmfFileGetReadStatus,
OmfFileSeek,
OmfFileWrite,
OmfFileGetFileInformation,
OmfFileSetFileInformation,
NULL,
OmfFileGetDirectoryEntry
};
// ----------------------------------------------------------------------------
// PROCEDURE: OmfOpen:
//
// DESCRIPTION: The routine opens the newest version/revision of OMF for
// the specified Product ID.
//
// a) It reads the EISAROM bit of the <device> component of
// the Path argument on the EISA bus spcified by the key of
// the <adapter> component of Path argument.
// b) If this bit is one, then a byte checksum is performed on
// the ROM-based OMF header and OMF directory.
// The Product ID, Firmware Version and Revision fields
// values are retained for the next operations.
// c) Next, the partitions, specified by the FWSearchPath
// environment variable are searched for files of the
// following form in the \eisa\omf subdirectory:
//
// <device>"V".LF"R"
//
// <device> = EISA Product ID (7 chars)
// "V" = version ([0-9],[A-Z])
// "R" = revision ([0-9],[A-Z])
//
// d) The OMF FAT file (or ROM) with a greater value of version-
// revision and with a correct checksum is used.
// f) Initialize some data structures
//
// When Open is used to access an OMF as a raw device, all input
// functions are permitted. These functions include Read, Seek
// and Close. Read and Seek are bounded by the current OMF size.
// For example, to read the OMF of a serial options board that was
// in slot 3 of EISA bus 0 as raw device, create and Open a path
// as follows: eisa(0)serial(3)omf() .
//
// ARGUMENTS: OpenPath Supplies a pointer to a zero terminated device
// path name.
// OpenMode Supplies the mode of the open.
// FileId Supplies a pointer to a variable that specifies
// the file table entry that is to be filled in
// if the open is successful.
//
// RETURN: ESUCCESS is returned if the open operation is successful.
// ENODEV the device portion of the pathname is invalid
//
//
// ASSUMPTIONS:
//
// CALLS:
//
// GLOBALS:
//
// NOTES:
// ----------------------------------------------------------------------------
//
ARC_STATUS
OmfOpen
(
IN PCHAR OpenPath,
IN OPEN_MODE OpenMode,
IN OUT PULONG FileId
)
{
//
// initialize local variables
//
LARGE_INTEGER Offset; // large interger for seek operations
ULONG SlotNumber; // eisa slot number
CHAR EisaCtrlMnemonic[ MAX_MNEMONIC_LEN +1 ]; // eisa ctrl mnemonic name
UCHAR IdInfo; // info id byte
PVOID IoBusAddress; // eisa I/O base address (virtual)
PUCHAR SlotAddress; // I/O address
BOOLEAN OmfRomOk=FALSE; // OMF ROM initialization flag
BOOLEAN OmfFatFileOk=FALSE; // OMF FAT file initialization flag
ULONG Count; // # of bytes transferred
PCHAR PFwSearchPath; // system partitions list pointer
CHAR OmfPathName[MAX_PATH_LEN +1]; // directory+subdirectory+file name
CHAR OmfPathBuffer[MAX_PATH_LEN +1] = {'\0'}; // OMF path name buffer
CHAR OmfFatFileName[]=" .LF "; // omf name (FAT format)
ULONG OmfSubdirId; // file Id of \eisa\omf subdirectory
POMF_HEADER_CONTEXT POmfHeaderContext; // OMF header context pointer
POMF_HDR POmfHeader; // pointer to OMF ROM/FAT file header
DIRECTORY_ENTRY DirEntBuffer; // ARC directory entry
PRINTDBG("OmfOpen\n\r"); // debug support
//
// this is a read only device
//
if ( OpenMode != ArcOpenReadOnly )
{
return EROFS;
}
//
// The path must have the following form : eisa(x)"mnemonic"(y)omf()
// Get EISA ID, slot number and its I/O address space.
//
if ( !FwGetNextMnemonic( OpenPath, "eisa", EisaCtrlMnemonic )
||
!FwGetMnemonicKey( OpenPath, EisaCtrlMnemonic, &SlotNumber )
||
!FwGetMnemonicPath( OpenPath, EisaCtrlMnemonic, OmfPathName )
||
!FwGetEisaId( OmfPathName, OmfFatFileName, &IdInfo )
||
!FwGetMnemonicPath( OpenPath,"eisa",OmfPathName )
||
!FwGetEisaBusIoCpuAddress( OmfPathName, &IoBusAddress ) )
{
return ENODEV;
}
//
// Initialize some variables
//
POmfHeaderContext = &BlFileTable[ *FileId ].u.OmfHeaderContext;
POmfHeader = &POmfHeaderContext->OmfHeader;
SlotAddress = (PUCHAR)IoBusAddress + SlotNumber * 0x1000;
Offset.LowPart = 0; // seek operation
Offset.HighPart = 0; // seek operation
//
// Check EISAROM bit of the Expansion Board Control Bits field.
// If the EISA ID is readable, the controller supports the EISA extensions
//
// DEBUG-DEBUG : for now skip the OMF ROM check because
// at the moment there isn't any board available
// with an OMF ROM to test the routine.
#if 0
if ( !(IdInfo & CFG_UNREADABLE_ID) &&
READ_PORT_UCHAR( SlotAddress + EXPANSION_BOARD_CTRL_BITS ) &
EISAROMBIT )
{
//
// initialize some fields to direct the OmfRead to the ROM
//
POmfHeaderContext->RomIndex = (PULONG)(SlotAddress+ROMINDEX);
POmfHeaderContext->RomRead = (PULONG)(SlotAddress+ROMREAD);
POmfHeaderContext->FileId = DEVICE_DEVICE;
POmfHeader->FwSize = 0; // max length simulation
//
// check OMF ROM header, copy it in the OmfHeaderContext structure
//
if ( !OmfSeek( *FileId, &Offset, SeekAbsolute)
&&
!OmfRead( *FileId,
(PVOID)POmfHeader,
(ULONG)sizeof(OMF_HDR),
&Count )
&&
OmfHeaderValidate( *FileId ) )
{
//
// copy version and revision
//
((POMF_FAT_FILE_NAME)OmfFatFileName)->Version =
POmfHeader->FwVersion;
((POMF_FAT_FILE_NAME)OmfFatFileName)->Revision =
POmfHeader->FwRevision;
//
// OMF ROM initialization has been done
//
OmfRomOk=TRUE;
}
}
#endif
//
// Set the current FileId to "open" so that calls to FwOpen won't use
// this FileId. This will get reset later.
//
BlFileTable[ *FileId ].Flags.Open = 1;
//
// check now if there is any file that upgrades the OFM ROM firmware.
// the partitions, specified by the FWSearchPath environment variable,
// are searched for files of the following form in the \eisa\omf
// subdirectory:
// <device>"V".LF"R"
//
// <device> = EISA Product ID (7 chars)
// "V" = version ([0-9],[A-Z])
// "R" = revision ([0-9],[A-Z])
//
if ( (PFwSearchPath = FwGetEnvironmentVariable("FWSearchPath")) != NULL )
{
//
// check all the directories specified by FWSearchPath
//
while ( GetNextPath( &PFwSearchPath, OmfPathName ))
{
//
// open the directory
//
strcat(OmfPathName, "\\eisa\\omf" );
if ( FwOpen( OmfPathName, ArcOpenDirectory, &OmfSubdirId ))
{
//
// Go check next path
//
continue;
}
//
// Check all files within the directory
//
while (!FwGetDirectoryEntry ( OmfSubdirId, &DirEntBuffer,
(ULONG) 1, &Count) )
{
//
// check directory flag, length of file name and file name
//
if ( !( DirEntBuffer.FileAttribute & ArcDirectoryFile )
&&
DirEntBuffer.FileNameLength
&&
MaxOmfFatFiles( OmfFatFileName, DirEntBuffer.FileName ))
{
//
// correct name, save file path
//
strcat( strcpy(OmfPathBuffer, OmfPathName), "\\" );
strcat(OmfPathBuffer, OmfFatFileName);
}
}
//
// close directory before opening the next
//
FwClose( OmfSubdirId );
}
}
//
// check for a valid OMF FAT file name
//
if ( OmfPathBuffer[0] )
{
//
// open file
//
if (FwOpen(OmfPathBuffer, ArcOpenReadOnly, &POmfHeaderContext->FileId))
{
//
// return with error
//
BlFileTable[ *FileId ].Flags.Open = 0;
return ENODEV;
}
POmfHeader->FwSize=0; // max length simulation
//
// validate header and copy data in the OmfHeaderContext structure
//
if ( OmfSeek( *FileId, &Offset, SeekAbsolute )
||
OmfRead( *FileId,
(PVOID)POmfHeader,
(ULONG)sizeof(OMF_HDR),
&Count)
||
!OmfHeaderValidate( *FileId ) )
{
PRINTDBG("No OK\n\r");
//
// close file and return with error
//
FwClose(POmfHeaderContext->FileId);
BlFileTable[ *FileId ].Flags.Open = 0;
return ENODEV;
}
//
// OMF FAT file initialization is done.
//
PRINTDBG("It's OK\n\r");
OmfFatFileOk=TRUE;
}
//
// Reset the open flag.
//
BlFileTable[ *FileId ].Flags.Open = 0;
//
// if OMF initialization not done, return error
//
// if ( !OmfRomOk && !OmfFatFileOk )
if ( !OmfFatFileOk )
{
return ENOENT;
}
else
{
BlFileTable[ *FileId ].Position.LowPart=0;
BlFileTable[ *FileId ].Position.HighPart=0;
return ESUCCESS;
}
}
// ----------------------------------------------------------------------------
// PROCEDURE: OmfClose:
//
// DESCRIPTION: The routine closes the file table entry specified by file id.
// If a OMF FAT file has been used, the routine calls the FwClose
// function using its file table entry (file id).
// the routine uses the following logic :
//
// if (OMF FAT file)
// {
// close file;
// if (error closing file)
// return error;
// }
// reset open flag;
// return ok;
//
// ARGUMENTS: FileId Supplies a pointer to a variable that specifies
// the file table entry.
//
// RETURN: ESUCCESS is returned if the open operation is successful.
// EBADF invalid file descriptor
//
//
// ASSUMPTIONS:
//
// CALLS:
//
// GLOBALS:
//
// NOTES:
// ----------------------------------------------------------------------------
//
ARC_STATUS
OmfClose
(
IN ULONG FileId
)
{
//
// initialize local variables
//
ARC_STATUS Status; // store return status from FwClose
//
// if OMF FAT file is used, call FwClose using its file table index
//
PRINTDBG("OmfClose\n\r");
if ( BlFileTable[ FileId ].DeviceId != DEVICE_DEVICE)
{
return EBADF;
}
if ( BlFileTable[ FileId ].u.OmfHeaderContext.FileId != DEVICE_DEVICE
&&
(Status = FwClose( BlFileTable[ FileId ].u.OmfHeaderContext.FileId)))
{
return Status;
}
//
// all done, return ok
//
BlFileTable[ FileId ].Flags.Open = 0;
return ESUCCESS;
}
// ----------------------------------------------------------------------------
// PROCEDURE: OmfMount:
//
// DESCRIPTION: The routine does nothing and return EBADF.
//
// ARGUMENTS: MountPath device path specifier.
// Operation mount operation (load/unload).
//
// RETURN: EBADF invalid operation
//
// ASSUMPTIONS:
//
// CALLS:
//
// GLOBALS:
//
// NOTES:
// ----------------------------------------------------------------------------
//
ARC_STATUS
OmfMount
(
IN PCHAR MountPath,
IN MOUNT_OPERATION Operation
)
{
//
// return error : invalid operation.
//
return EBADF;
}
// ----------------------------------------------------------------------------
// PROCEDURE: OmfRead:
//
// DESCRIPTION: This routine implements the read operation for the ARC-EISA
// firmware "OMF" driver.
//
// ARGUMENTS: FileId Supplies a pointer to a variable that specifies
// the file table entry.
// Buffer Supplies a pointer to a buffer where the
// characters read will be stored.
// Length Supplies the length of Buffer.
// Count Return the count of the characters that
// were read.
//
// RETURN: ESUCCESS is returned if the open operation is successful.
//
// ASSUMPTIONS:
//
// CALLS:
//
// GLOBALS:
//
// NOTES:
// ----------------------------------------------------------------------------
//
ARC_STATUS
OmfRead
(
IN ULONG FileId,
IN PVOID Buffer,
IN ULONG Length,
OUT PULONG Count
)
{
//
// initialize local variables
//
ARC_STATUS Status; // ARC status
POMF_HEADER_CONTEXT POmfHeaderContext; // OMF header context pointer
ULONG OmfSize; // OMF firmware size (bytes)
PLARGE_INTEGER PPosition; // file/device position field pointer
USHORT ByteIndex; // byte index within the word
ULONG WordBuffer; // 1 word buffer
PRINTDBG("OmfRead\n\r");
//
// Initialize some variables
//
POmfHeaderContext = &BlFileTable[ FileId ].u.OmfHeaderContext;
//
// compute OMF length in bytes
//
OmfSize = (ULONG)POmfHeaderContext->OmfHeader.FwSize * OMF_BLOCK_SIZE;
if ( !OmfSize )
{
OmfSize = OMF_MAX_SIZE;
}
//
// initialize byte count read to zero and position variable
//
*Count = 0;
PPosition = &BlFileTable[ FileId ].Position;
//
// if length is zero or end of "file", return ESUCCESS.
//
if ( !Length || PPosition->LowPart >= OmfSize )
{
return ESUCCESS;
}
//
// adjust length if it is too big.
//
Length = MIN( Length, OmfSize ); // to prevent the add to overflow
if ( PPosition->LowPart + Length > OmfSize )
{
Length = OmfSize - PPosition->LowPart;
}
//
// if OMF FAT file, read from file.
//
if ( POmfHeaderContext->FileId != DEVICE_DEVICE )
{
if ( !(Status = FwSeek( POmfHeaderContext->FileId,
PPosition,
SeekAbsolute ))
&&
!(Status = FwRead( POmfHeaderContext->FileId,
Buffer,
Length,
Count )) )
{
PPosition->LowPart += *Count;
}
return Status;
}
//
// write word index and compute starting byte index (within a word)
//
WRITE_PORT_ULONG(POmfHeaderContext->RomIndex,
PPosition->LowPart >> WORD_2P2 );
//
// read OMF ROM
// one loop per word
//
while ( Length )
{
ByteIndex = (USHORT) (PPosition->LowPart & (1<<WORD_2P2)-1);
//
// read the whole word if the buffer and OMF pointers are
// word aligned.
// // |
if ( !ByteIndex // DEBUG V
&&
!((USHORT)((PUCHAR)Buffer + *Count) & (1 << WORD_2P2) -1 ) )
{
while ( Length >= (1 << WORD_2P2) )
{
*((PULONG)( (PUCHAR)Buffer + *Count ))=
READ_PORT_ULONG( POmfHeaderContext->RomRead );
*Count += 1<<WORD_2P2;
Length -= 1<<WORD_2P2;
}
}
//
// read the word in bytes units if the buffer or the OMF pointers
// are not word aligned or if just part of the word is needed.
//
if ( Length )
{
WordBuffer = READ_PORT_ULONG( POmfHeaderContext->RomRead );
//
// read just the selected bytes
//
while ( ByteIndex < (1 << WORD_2P2) && Length-- )
{
*( (PUCHAR)Buffer + *Count++ )=
(UCHAR)( WordBuffer >> BITSXBYTE * ByteIndex++ );
}
}
//
// update OMF pointer
//
PPosition->LowPart += *Count;
}
//
// return all done
//
return ESUCCESS;
}
// ----------------------------------------------------------------------------
// PROCEDURE: OmfWrite:
//
// DESCRIPTION: This routine implements the write operation for the ARC-EISA
// firmware "OMF" driver.
//
// ARGUMENTS: FileId Supplies a pointer to a variable that specifies
// the file table entry.
// Buffer Supplies a pointer to a buffer where the
// characters are read.
// Length Supplies the length of Buffer.
// Count Return the count of the characters that
// were written.
//
// RETURN: EBADF invalid operation
//
// ASSUMPTIONS:
//
// CALLS:
//
// GLOBALS:
//
// NOTES:
// ----------------------------------------------------------------------------
//
ARC_STATUS
OmfWrite
(
IN ULONG FileId,
IN PVOID Buffer,
IN ULONG Length,
OUT PULONG Count
)
{
//
// return error : invalid operation
//
return EBADF;
}
// ----------------------------------------------------------------------------
// PROCEDURE: OmfGetReadStatus:
//
// DESCRIPTION: This routine implements the GetReadStatus operation for the
// ARC-EISA firmware "OMF" driver.
//
// ARGUMENTS: FileId Supplies a pointer to a variable that specifies
// the file table entry.
//
// RETURN: ESUCCESS return always success.
//
// ASSUMPTIONS:
//
// CALLS:
//
// GLOBALS:
//
// NOTES:
// ----------------------------------------------------------------------------
//
ARC_STATUS
OmfGetReadStatus
(
IN ULONG FileId
)
{
//
// return ok
//
return ESUCCESS;
}
// ----------------------------------------------------------------------------
// PROCEDURE: OmfSeek:
//
// DESCRIPTION: This routine implements the Seek operation for the
// ARC-EISA firmware "OMF" driver.
//
// ARGUMENTS: FileId Supplies a pointer to a variable that specifies
// the file table entry.
// Offset Supplies the offset in the file to position to.
// SeekMode Supplies the mode of the seek operation
//
// RETURN: ESUCCESS returned if the operation is successful.
// EINVAL returned otherwise.
//
// ASSUMPTIONS:
//
// CALLS:
//
// GLOBALS:
//
// NOTES:
// ----------------------------------------------------------------------------
//
ARC_STATUS
OmfSeek
(
IN ULONG FileId,
IN PLARGE_INTEGER Offset,
IN SEEK_MODE SeekMode
)
{
//
// local variables
//
LARGE_INTEGER Point; // New position
ULONG OmfSize; // OMF size in bytes
PRINTDBG("OmfSeek\n\r");
//
// initialize some variables
//
OmfSize = (ULONG)BlFileTable[ FileId ].u.OmfHeaderContext.OmfHeader.FwSize *
OMF_BLOCK_SIZE;
if ( !OmfSize )
{
OmfSize=OMF_MAX_SIZE;
}
//
// compute new offset value
//
switch( SeekMode )
{
case SeekAbsolute:
Point = *Offset;
break;
case SeekRelative:
Point = RtlLargeIntegerAdd( BlFileTable[FileId].Position, *Offset );
break;
default:
return EINVAL;
}
//
// if the high 32 bits are not zero, return an error.
// if new offset is valid, update position field.
// if the position value 0-based is equal to the OMF size (1-based),
// the EOF has been reached. no error is returned in this case and
// the count field is set to zero with ESUCCESS error code for any
// successive read operation. note that this combination (ESUCCESS and
// count=0) is used to rappresent EOF (end of file).
//
if ( Point.HighPart || Point.LowPart > OmfSize )
{
return EINVAL;
}
else
{
BlFileTable[FileId].Position = Point;
return ESUCCESS;
}
}
// ----------------------------------------------------------------------------
// PROCEDURE: OmfGetFileInformation:
//
// DESCRIPTION: This routine implements the GetFileInformation for the
// ARC-EISA firmware "OMF" driver.
//
// ARGUMENTS: FileId Supplies the file table index.
// Buffer Supplies the buffer to receive the file
// information. Note that it must be large
// enough to hold the full file name.
//
// RETURN: EBADF invalid operation
//
// ASSUMPTIONS:
//
// CALLS:
//
// GLOBALS:
//
// NOTES:
// ----------------------------------------------------------------------------
//
ARC_STATUS
OmfGetFileInformation
(
IN ULONG FileId,
OUT PFILE_INFORMATION Buffer
)
{
//
// return error : invalid operation
//
return EBADF;
}
// ----------------------------------------------------------------------------
// PROCEDURE: OmfSetFileInformation:
//
// DESCRIPTION: This routine implements the SetFileInformation for the
// ARC-EISA firmware "OMF" driver.
//
// ARGUMENTS: FileId Supplies the file table index.
// AttributeFlags Supplies the value (on or off) for each
// attribute being modified.
// AttributeMask Supplies a mask of the attributes being altered.
// All other file attributes are left alone.
//
// RETURN: EBADF invalid operation
//
// ASSUMPTIONS:
//
// CALLS:
//
// GLOBALS:
//
// NOTES:
// ----------------------------------------------------------------------------
//
ARC_STATUS
OmfSetFileInformation
(
IN ULONG FileId,
IN ULONG AttributeFlags,
IN ULONG AttributeMask
)
{
//
// return error : invalid operation
//
return EBADF;
}
// ----------------------------------------------------------------------------
// PROCEDURE: OmfGetDirectoryEntry:
//
// DESCRIPTION: This routine implements the GetDirectoryEntry for the
// ARC-EISA firmware "OMF" driver.
//
// ARGUMENTS: FileId Supplies the file table index.
// DirEntry Pointer to a directory entry structure
// NumberDir # of entries to read
// Count # of entries read
//
// RETURN: EBADF directory operations are not supported
//
// ASSUMPTIONS:
//
// CALLS:
//
// GLOBALS:
//
// NOTES:
// ----------------------------------------------------------------------------
//
ARC_STATUS
OmfGetDirectoryEntry
(
IN ULONG FileId,
IN DIRECTORY_ENTRY *DirEntry,
IN ULONG NumberDir,
OUT PULONG CountDir
)
{
//
// return error : directory operations are not supported
//
return EBADF;
}
// ----------------------------------------------------------------------------
// PROCEDURE: OmfFileOpen:
//
// DESCRIPTION: The routine opens the OMF file.
// The <extension> of the <filename> is optional. The caller can
// make the following assumptions if the <extension> is not
// included in the <filename> :
// . the firmware searches for folders whose type is MIPS first.
// This is equivalent to using '.A' as the <extension>. If
// the requested folder of this type is found in the most recent
// OMF, then this folder is used.
// . If the modst recent OMF does not contain the requested folder
// whose type is MIPS, then the SMF searches for the requested
// folder whose type is BINARY. This is equivalent to using '.B'
// as the <extension>. If the requested folder of this type is
// found in the most recent OMF then this folder is used.
// . If there are no folders with either type in the most recent
// OMF, the operation fails.
//
// When omf() is used as <protocol spec> and the filename is the
// string "\", the path specification represents the OMF directory.
// The only valid operation to perform on the OMF directory is to
// Open it, then use FwGetDirectoryEntry to enumerate the folders
// within the OMF, and then Close it. For example, to
// enumerate all folders that are containded in the OMF of a
// serail options board that was in slot 3 of EISA bus0, create
// and Open a path as follows : eisa(0)serial(3)omf()\ .
// To open the diagnostic folder for the above EISA option board
// the system utilty would create and Open the path specification :
// eisa(0)serial(3)omf()\T-SERIAL.
//
//
// ARGUMENTS: OpenPath Supplies a pointer to a zero terminated OMF
// file name.
// OpenMode Supplies the mode of the open.
// FileId Supplies the file table entry index
//
// RETURN: ESUCCESS is returned if the open operation is successful.
// ENOENT the named device or file does not exist.
//
//
// ASSUMPTIONS:
//
// CALLS:
//
// GLOBALS:
//
// NOTES:
// ----------------------------------------------------------------------------
//
ARC_STATUS
OmfFileOpen
(
IN PCHAR OpenPath,
IN OPEN_MODE OpenMode,
IN OUT PULONG FileId
)
{
//
// initialize local variables
//
ARC_STATUS Status; // ARC status
ULONG DeviceId; // device table entry index
POMF_DIR_ENT POmfDirEnt; // OMF directory entry pointer
POMF_HDR POmfHeader; // OMF header pointer
LARGE_INTEGER AbsolutePosition; // position
ULONG TypeIndex,DirIndex; // general indexes
ULONG Count; // # of bytes transferred
CHAR OmfFileName[OMF_FILE_NAME_LEN]; // folder name
BOOLEAN SearchSucceeded = FALSE; // match flag
BOOLEAN IsDirectory = FALSE; // directory flag
CHAR OmfType[] = {'A','B','\0'}; // default sequance of search:
// relocatable MIPS I object
// format binary data format
// end of chain
PRINTDBG("OmfFileOpen\n\r"); // debug support
//
// Initialize some variables
//
DeviceId = BlFileTable[ *FileId ].DeviceId;
POmfDirEnt = &BlFileTable[ *FileId ].u.OmfFileContext.OmfDirEnt;
POmfHeader = &BlFileTable[ DeviceId ].u.OmfHeaderContext.OmfHeader;
AbsolutePosition.HighPart=0; // for seek operations
//
// initialize the file/directory pointer to zero
//
BlFileTable[ *FileId ].Position.LowPart=0;
BlFileTable[ *FileId ].Position.HighPart=0;
//
// the first char must be the directory char, otherwise it's an error
//
if ( *OpenPath++ != '\\' );
//
// else check if the open is for the root directory
//
else if ( *OpenPath == '\0' )
{
POmfDirEnt->FolderName[0]='\0';
SearchSucceeded = TRUE;
IsDirectory = TRUE;
}
//
// else validate OMF file name
//
else if ( !OmfFileNameValidate( OpenPath, OmfFileName, OmfType ));
//
// then search the specified file name
//
else
{
//
// save the omf file name
//
strcpy( BlFileTable[ *FileId ].FileName, OpenPath );
BlFileTable[ *FileId ].FileNameLength = strlen( OpenPath );
//
// one loop per file
//
for (TypeIndex = 0; !SearchSucceeded && OmfType[TypeIndex]; TypeIndex++)
{
//
// search the directory for the specified OMF file name
//
for ( DirIndex = 0, AbsolutePosition.LowPart =
POmfHeader->FolderDirectoryLink << WORD_2P2;
DirIndex < POmfHeader->FolderCount && !SearchSucceeded;
DirIndex++, AbsolutePosition.LowPart += sizeof(OMF_DIR_ENT) )
{
//
// exit if error during seek or read.
//
if ((Status = FwSeek(DeviceId, &AbsolutePosition, SeekAbsolute))
||
(Status = FwRead(DeviceId,
(PVOID)POmfDirEnt,
(ULONG)sizeof(OMF_DIR_ENT),
&Count )))
{
return Status;
}
//
// check OMF file name
//
SearchSucceeded = CmpOmfFiles( OmfFileName,
OmfType[TypeIndex],
(PVOID)POmfDirEnt );
}
}
//
// if the search has been successful, validate file's header
//
if (SearchSucceeded && !OmfFileValidate( *FileId ))
{
SearchSucceeded = FALSE;
}
}
//
// At this point we've cracked the name up to (an maybe including the last
// component). We located the last component if the SearchSucceeded flag
// is true, otherwise the last component does not exist. If we located
// the last component then this is like an open or a supersede, but not a
// create.
//
if (SearchSucceeded)
{
//
// Check if the last component is a directory
//
if (IsDirectory)
{
//
// For an existing directory the only valid open mode is
// OpenDirectory all other modes return an error
//
switch (OpenMode)
{
case ArcOpenReadOnly:
case ArcOpenWriteOnly:
case ArcOpenReadWrite:
case ArcCreateWriteOnly:
case ArcCreateReadWrite:
case ArcSupersedeWriteOnly:
case ArcSupersedeReadWrite:
//
// if we reach here then the caller got a directory but
// didn't want to open a directory
//
return EISDIR;
case ArcOpenDirectory:
//
// if we reach here then the caller got a directory and
// wanted to open a directory.
//
BlFileTable[ *FileId ].Flags.Open = 1;
BlFileTable[ *FileId ].Flags.Read = 1;
return ESUCCESS;
case ArcCreateDirectory:
//
// if we reach here then the caller got a directory and
// wanted to create a new directory
//
return EACCES;
default:
//
// invalid open mode
//
return EINVAL;
}
}
//
// If we get there then we have an existing file that is being opened.
// We can open existing files only read only.
//
switch (OpenMode)
{
case ArcOpenReadOnly:
//
// if we reach here then the user got a file and wanted to
// open the file read only
//
BlFileTable[ *FileId ].Flags.Open = 1;
BlFileTable[ *FileId ].Flags.Read = 1;
return ESUCCESS;
case ArcOpenWriteOnly:
case ArcOpenReadWrite:
case ArcCreateWriteOnly:
case ArcCreateReadWrite:
case ArcSupersedeWriteOnly:
case ArcSupersedeReadWrite:
//
// if we reach here then we are trying to open a read only
// device for write.
//
return EROFS;
case ArcOpenDirectory:
case ArcCreateDirectory:
//
// if we reach here then the user got a file and wanted a
// directory
//
return ENOTDIR;
default:
//
// invalid open mode
//
return EINVAL;
}
}
//
// If we get here the last component does not exist so we are trying to
// create either a new file or a directory.
//
switch (OpenMode)
{
case ArcOpenReadOnly:
case ArcOpenWriteOnly:
case ArcOpenReadWrite:
case ArcOpenDirectory:
//
// if we reach here then the user did not get a file but wanted
// a file
//
return ENOENT;
case ArcCreateWriteOnly:
case ArcSupersedeWriteOnly:
case ArcCreateReadWrite:
case ArcSupersedeReadWrite:
case ArcCreateDirectory:
//
// if we get hre the user wants to create something.
//
return EROFS;
default:
//
// invalid open mode
//
return EINVAL;
}
}
// ----------------------------------------------------------------------------
// PROCEDURE: OmfFileClose:
//
// DESCRIPTION: The routine closes the file table entry specified by file id.
//
// ARGUMENTS: FileId Supplies the file table index.
//
// RETURN: ESUCCESS is returned if the open operation is successful.
//
//
// ASSUMPTIONS:
//
// CALLS:
//
// GLOBALS:
//
// NOTES:
// ----------------------------------------------------------------------------
//
ARC_STATUS
OmfFileClose
(
IN ULONG FileId
)
{
PRINTDBG("OmfFileClose\n\r");
//
// clear flag and exit
//
BlFileTable[FileId].Flags.Open = 0;
return ESUCCESS;
}
// ----------------------------------------------------------------------------
// PROCEDURE: OmfFileMount:
//
// DESCRIPTION: The routine does nothing and return EBADF.
//
// ARGUMENTS: MountPath device path specifier.
// Operation mount operation (load/unload).
//
// RETURN: EBADF invalid operation
//
// ASSUMPTIONS:
//
// CALLS:
//
// GLOBALS:
//
// NOTES:
// ----------------------------------------------------------------------------
//
ARC_STATUS
OmfFileMount
(
IN PCHAR MountPath,
IN MOUNT_OPERATION Operation
)
{
//
// return error : invalid operation.
//
return EBADF;
}
// ----------------------------------------------------------------------------
// PROCEDURE: OmfFileGetReadStatus
//
// DESCRIPTION: This routine implements the GetReadStatus operation for the
// ARC-EISA firmware OMF file.
//
// ARGUMENTS: FileId Supplies a pointer to a variable that specifies
// the file table entry.
//
// RETURN: ESUCCESS return always success.
//
// ASSUMPTIONS:
//
// CALLS:
//
// GLOBALS:
//
// NOTES:
// ----------------------------------------------------------------------------
//
ARC_STATUS
OmfFileGetReadStatus
(
IN ULONG FileId
)
{
//
// return ok
//
return ESUCCESS;
}
// ----------------------------------------------------------------------------
// PROCEDURE: OmfFileRead:
//
// DESCRIPTION: This routine implements the read operation for the ARC-EISA
// firmware "OMF" driver.
//
// ARGUMENTS: FileId Supplies the file table index.
// Buffer Supplies a pointer to a buffer where the
// characters read will be stored.
// Length Supplies the length of Buffer.
// Count Return the count of the characters that
// were read.
//
// RETURN: ESUCCESS is returned if the open operation is successful.
//
// ASSUMPTIONS:
//
// CALLS:
//
// GLOBALS:
//
// NOTES:
// ----------------------------------------------------------------------------
//
ARC_STATUS
OmfFileRead
(
IN ULONG FileId,
IN PVOID Buffer,
IN ULONG Length,
OUT PULONG Count
)
{
//
// initialize local variables
//
ARC_STATUS Status; // ARC status
POMF_DIR_ENT POmfDirEnt; // OMF directory entry pointer
LARGE_INTEGER AbsolutePosition; // OMF file, logical pointer
ULONG OmfFileSize; // OMF file size in bytes
PRINTDBG("OmfFileRead\n\r");
//
// initialize some variables
//
POmfDirEnt = &BlFileTable[ FileId ].u.OmfFileContext.OmfDirEnt;
//
// if directory entry, exit with error
//
if ( !POmfDirEnt->FolderName[0] )
{
return EBADF; // check this error code "EGI_Q"
}
//
// initialize byte count read to zero
//
*Count=0;
OmfFileSize = POmfDirEnt->FolderSize << WORD_2P2;
//
// if length is zero or EOF (end of file), return ESUCCESS.
//
if (!Length || BlFileTable[FileId].Position.LowPart >= OmfFileSize)
{
return ESUCCESS;
}
//
// adjust length if it is too big.
//
Length = MIN( Length, OmfFileSize ); // to prevent the add to overflow
if ( BlFileTable[ FileId ].Position.LowPart + Length > OmfFileSize )
{
Length = OmfFileSize - BlFileTable[ FileId ].Position.LowPart;
}
//
// find OMF absolute offset from OMF file absolute offset
//
AbsolutePosition.HighPart = 0;
AbsolutePosition.LowPart = BlFileTable[ FileId ].Position.LowPart +
( POmfDirEnt->FolderLink << WORD_2P2 );
//
// seek + read command
//
if ( (Status = FwSeek( BlFileTable[ FileId ].DeviceId,
&AbsolutePosition,
SeekAbsolute ))
||
(Status = FwRead( BlFileTable[FileId].DeviceId,
Buffer,
Length,
Count )) )
{
return Status;
}
//
// update file pointer and exit
//
BlFileTable[FileId].Position.LowPart += *Count;
return ESUCCESS;
}
// ----------------------------------------------------------------------------
// PROCEDURE: OmfFileWrite:
//
// DESCRIPTION: This routine implements the write operation for the ARC-EISA
// firmware "OMF" driver.
//
// ARGUMENTS: FileId Supplies the file table index.
// Buffer Supplies a pointer to a buffer where the
// characters are read.
// Length Supplies the length of Buffer.
// Count Return the count of the characters that
// were written.
//
// RETURN: EBADF invalid operation
//
// ASSUMPTIONS:
//
// CALLS:
//
// GLOBALS:
//
// NOTES:
// ----------------------------------------------------------------------------
//
ARC_STATUS
OmfFileWrite
(
IN ULONG FileId,
IN PVOID Buffer,
IN ULONG Length,
OUT PULONG Count
)
{
//
// return error : invalid operation
//
return EBADF;
}
// ----------------------------------------------------------------------------
// PROCEDURE: OmfFileSeek:
//
// DESCRIPTION: This routine implements the Seek operation for the
// ARC-EISA firmware "OMF" driver.
//
// ARGUMENTS: FileId Supplies the file table index.
// Offset Supplies the offset in the file to position to.
// SeekMode Supplies the mode of the seek operation
//
// RETURN: ESUCCESS returned if the operation is successful.
// EINVAL returned otherwise.
//
// ASSUMPTIONS:
//
// CALLS:
//
// GLOBALS:
//
// NOTES:
// ----------------------------------------------------------------------------
//
ARC_STATUS
OmfFileSeek
(
IN ULONG FileId,
IN PLARGE_INTEGER Offset,
IN SEEK_MODE SeekMode
)
{
//
// local variables
//
LARGE_INTEGER Point; // New position
POMF_DIR_ENT POmfDirEnt; // OMF directory entry pointer
PRINTDBG("OmfFileSeek\n\r");
//
// initialize some variables
//
POmfDirEnt = &BlFileTable[ FileId ].u.OmfFileContext.OmfDirEnt;
//
// The offset parameter must be zero, if directory entry.
//
if ( !POmfDirEnt->FolderName[0] && ( Offset->LowPart || Offset->HighPart ))
{
return EINVAL;
}
//
// compute new offset value
//
switch(SeekMode)
{
case SeekAbsolute:
Point = *Offset;
break;
case SeekRelative:
Point = RtlLargeIntegerAdd( BlFileTable[FileId].Position, *Offset );
break;
default:
return EINVAL;
}
//
// if new offset is valid, update position field.
// if the position value 0-based is equal to the OMF size (1-based),
// the EOF has been reached. no error is returned in this case and
// the count field is set to zero with ESUCCESS error code for any
// successive read operation. note that this combination (ESUCCESS and
// count=0) is used to rappresent EOF (end of file).
//
if ( POmfDirEnt->FolderName[0] &&
(Point.HighPart || Point.LowPart > POmfDirEnt->FolderSize << WORD_2P2))
{
return EINVAL;
}
else
{
BlFileTable[ FileId ].Position = Point;
return ESUCCESS;
}
}
// ----------------------------------------------------------------------------
// PROCEDURE: OmfFileGetFileInformation:
//
// DESCRIPTION: This routine implements the GetFileInformation for the
// ARC-EISA firmware "OMF" driver.
//
// ARGUMENTS: FileId Supplies the file table index.
// Buffer Supplies the buffer to receive the file
// information. Note that it must be large
// enough to hold the full file name.
//
// RETURN: EBADF invalid operation
//
// ASSUMPTIONS:
//
// CALLS:
//
// GLOBALS:
//
// NOTES:
// ----------------------------------------------------------------------------
//
ARC_STATUS
OmfFileGetFileInformation
(
IN ULONG FileId,
OUT PFILE_INFORMATION Buffer
)
{
//
// define local variable
//
PBL_FILE_TABLE FileTableEntry = &BlFileTable[ FileId ];
PRINTDBG("OmfFileGetFileInformation\n\r");
//
// if root, exit with error
//
if ( !FileTableEntry->u.OmfFileContext.OmfDirEnt.FolderName[0] )
{
return EBADF;
}
//
// set output fields
//
RtlZeroMemory(Buffer, sizeof(FILE_INFORMATION));
//
// ending address (high part is already zero) and current address
//
Buffer->EndingAddress.LowPart =
FileTableEntry->u.OmfFileContext.OmfDirEnt.FolderSize << WORD_2P2;
Buffer->CurrentPosition.LowPart = FileTableEntry->Position.LowPart;
Buffer->CurrentPosition.HighPart = FileTableEntry->Position.HighPart;
//
// device type
//
Buffer->Type = OtherPeripheral;
//
// file name length, attributes and file name string
//
Buffer->FileNameLength = FileTableEntry->FileNameLength;
Buffer->Attributes = ArcReadOnlyFile;
strcpy( Buffer->FileName, FileTableEntry->FileName );
//
// all done
//
return ESUCCESS;
}
// ----------------------------------------------------------------------------
// PROCEDURE: OmfFileSetFileInformation:
//
// DESCRIPTION: This routine implements the SetFileInformation for the
// ARC-EISA firmware "OMF" driver.
//
// ARGUMENTS: FileId Supplies the file table index.
// AttributeFlags Supplies the value (on or off) for each
// attribute being modified.
// AttributeMask Supplies a mask of the attributes being altered.
// All other file attributes are left alone.
//
// RETURN: EBADF invalid operation
//
// ASSUMPTIONS:
//
// CALLS:
//
// GLOBALS:
//
// NOTES:
// ----------------------------------------------------------------------------
//
ARC_STATUS
OmfFileSetFileInformation
(
IN ULONG FileId,
IN ULONG AttributeFlags,
IN ULONG AttributeMask
)
{
//
// return error : invalid operation
//
return EROFS;
}
// ----------------------------------------------------------------------------
// PROCEDURE: OmfFileGetDirectoryEntry:
//
// DESCRIPTION: This routine implements the GetDirectoryEntry for the
// ARC-EISA firmware "OMF" driver.
//
// ARGUMENTS: FileId Supplies the file table index.
// DirEntry Pointer to a directory entry structure
// NumberDir # of entries to read
// Count # of entries read
//
// RETURN: ESUCCESS returned if the operation is successful.
// EINVAL returned otherwise.
//
// ASSUMPTIONS:
//
// CALLS:
//
// GLOBALS:
//
// NOTES:
// ----------------------------------------------------------------------------
//
ARC_STATUS
OmfFileGetDirectoryEntry
(
IN ULONG FileId,
IN DIRECTORY_ENTRY *DirEntry,
IN ULONG NumberDir,
OUT PULONG CountDir
)
{
//
// initialize local variables
//
ARC_STATUS Status; // ARC status
ULONG DeviceId; // file table entry for the device
POMF_HDR POmfHeader; // pointer to OMF ROM/FAT file header
ULONG CurrentDir; // current directory entry
LARGE_INTEGER AbsolutePosition; // OMF file, pointer of logical pointer
OMF_DIR_ENT OmfFileBuffer; // buffer for directory entries
ULONG Count; // # of bytes read
PRINTDBG("OmfFileGetDirectoryEntry\n\r");
//
// if not directory entry, exit with error
//
if ( BlFileTable[ FileId ].u.OmfFileContext.OmfDirEnt.FolderName[0] )
{
return EBADF;
}
//
// Initialize the output count to zero
//
*CountDir=0;
//
// if NumberDir is zero, return ESUCCESS.
//
if ( !NumberDir )
{
return ESUCCESS;
}
//
// initialize variables
//
Count=0;
DeviceId = BlFileTable[ FileId ].DeviceId;
POmfHeader = &BlFileTable[ DeviceId ].u.OmfHeaderContext.OmfHeader;
CurrentDir = BlFileTable[ FileId ].Position.LowPart/sizeof(OMF_DIR_ENT);
//
// if no more entries, return ENOTDIR
//
if ( CurrentDir >= POmfHeader->FolderCount )
{
return ENOTDIR;
}
//
// adjust count if it is too big.
//
NumberDir = MIN( NumberDir, POmfHeader->FolderCount ); //avoid add overflow
if ( CurrentDir + NumberDir > POmfHeader->FolderCount )
{
NumberDir = POmfHeader->FolderCount - CurrentDir;
}
//
// find OMF absolute offset from OMF file absolute offset
//
AbsolutePosition.HighPart = 0;
AbsolutePosition.LowPart = BlFileTable[FileId].Position.LowPart +
(POmfHeader->FolderDirectoryLink<<WORD_2P2);
//
// seek command
//
if ( Status = FwSeek( DeviceId, &AbsolutePosition, SeekAbsolute ))
{
return Status;
}
//
// read command
//
while( NumberDir-- )
{
//
// read one directory entry
//
if ( Status = FwRead( DeviceId,
&OmfFileBuffer,
(ULONG)sizeof(OMF_DIR_ENT),
&Count ))
{
return Status;
}
//
// if bytes read are not sizeof(OMF_DIR_ENT), return error
//
if ( Count != sizeof(OMF_DIR_ENT) )
{
return EBADF;
}
//
// convert OMF directory entry in ARC directory entry
//
ConvertOmfDirToArcDir( &OmfFileBuffer, DirEntry++ );
++*CountDir;
}
//
// update file pointer and exit
//
BlFileTable[FileId].Position.LowPart += *CountDir * sizeof(OMF_DIR_ENT);
return ESUCCESS;
}
// ----------------------------------------------------------------------------
// PROCEDURE: MaxOmfFatFiles:
//
// DESCRIPTION: The routine returns the most updated file name for the
// specified product Id.
// A FALSE is returned if the OMF FAT file name has not been
// modified.
//
// ARGUMENTS: MasterName name used as base
// CheckedName name checked
//
// RETURN: TRUE is returned if the OMF FAT file name has been
// modified.
// FALSE is returned in all the other cases.
//
// ASSUMPTIONS:
//
// CALLS:
//
// GLOBALS:
//
// NOTES:
// ----------------------------------------------------------------------------
//
BOOLEAN
MaxOmfFatFiles
(
IN OUT PCHAR MasterName,
IN PCHAR CheckedName
)
{
//
// Define variables
//
CHAR MasterVersion, MasterRevision; // master name
CHAR CheckedVersion, CheckedRevision; // checked name
POMF_FAT_FILE_NAME PointerMaster; // master name pointer
POMF_FAT_FILE_NAME PointerChecked; // checked name pointer
PRINTDBG("MaxOmfFatFiles\n\r");
//
// save version and revision master values
//
PointerMaster = (POMF_FAT_FILE_NAME)MasterName;
MasterVersion = PointerMaster->Version;
MasterRevision = PointerMaster->Revision;
//
// save version and revision checked values
//
PointerChecked = (POMF_FAT_FILE_NAME)CheckedName;
CheckedVersion = PointerChecked->Version;
CheckedRevision = PointerChecked->Revision;
PointerChecked->Version = MasterVersion;
PointerChecked->Revision = MasterRevision;
//
// update name if new version for the same product Id
//
if (strcmp(MasterName, CheckedName)
||
CheckedVersion<MasterVersion
||
(CheckedVersion == MasterVersion && CheckedRevision <= MasterRevision))
{
return FALSE;
}
else
{
PointerMaster->Version = CheckedVersion;
PointerMaster->Revision = CheckedRevision;
return TRUE;
}
}
// ----------------------------------------------------------------------------
// PROCEDURE: OmfFileNameValidate:
//
// DESCRIPTION: The routine validates the requested OMF file name.
// The name is decomposed in Folder Name and Folder Type.
//
// ARGUMENTS: OpenPath Supplies a pointer to a zero terminated OMF
// file name.
// OmfFileName Supplies a pointer to an array used to store
// the Folder Name.
// OmfType Supplies a pointer to an array used to store
// the Folder Types.
//
// RETURN: TRUE is returned if the operation succeed.
// FALSE is returned if the OpenPath is incorrect.
//
// ASSUMPTIONS:
//
// CALLS:
//
// GLOBALS:
//
// NOTES:
// ----------------------------------------------------------------------------
//
BOOLEAN
OmfFileNameValidate
(
IN PCHAR OpenPath,
OUT PCHAR OmfFileName,
OUT PCHAR OmfType
)
{
//
// Define variables
//
ULONG NameIndex; // general index
PRINTDBG("OmfFileNameValidate\n\r");
//
// name validation
//
for ( NameIndex = 0;
NameIndex < OMF_FILE_NAME_LEN && *OpenPath && *OpenPath != '.';
NameIndex++ )
{
if (
isupper( *OpenPath ) // upper case letter
||
isdigit( *OpenPath ) // digit
||
*OpenPath=='-' // '-' minus
||
(*OpenPath=='$' && NameIndex==0) // $ char in 1st position
)
{
*OmfFileName++=*OpenPath++;
}
else
{
return FALSE;
}
}
//
// return error if name length > of OMF_FILE_NAME_LEN
//
if ( NameIndex == OMF_FILE_NAME_LEN && *OpenPath && *OpenPath != '.')
{
return FALSE;
}
//
// fill right with null chars ('\0') if Folder Name is less than 12 chars
//
while( NameIndex++ < OMF_FILE_NAME_LEN )
{
*OmfFileName++='\0';
}
//
// extension validation
//
if ( *OpenPath++ && *OpenPath ) // skip "null", ".null"
{
switch( *OpenPath ) // check type field
{
case 'A':
case 'B':
*OmfType++ = *OpenPath++;
*OmfType = '\0'; // means : end of types
break;
default:
return FALSE;
}
if( *OpenPath ) // error if more chars
{
return FALSE;
}
}
//
// all done, return ok
//
return TRUE;
}
// ----------------------------------------------------------------------------
// PROCEDURE: CmpOmfFiles:
//
// DESCRIPTION: The routine checks if the selected directory entry has the
// requested OMF file name.
//
// ARGUMENTS: OmfFileName Requested OMF file name pointer.
// OmfType Requested OMF file type pointer.
// POmfDirEnt Directory entry to check.
//
// RETURN: TRUE is returned if the operation succeed.
// FALSE is returned if the name or type doesn't match.
//
// ASSUMPTIONS:
//
// CALLS:
//
// GLOBALS:
//
// NOTES:
// ----------------------------------------------------------------------------
//
BOOLEAN
CmpOmfFiles
(
IN PCHAR OmfFileName,
IN CHAR OmfType,
IN POMF_DIR_ENT POmfDirEnt
)
{
//
// Define variables
//
ULONG NameIndex; // general index
PRINTDBG("CmpOmfFiles\n\r");
//
// check name
//
for ( NameIndex=0; NameIndex < OMF_FILE_NAME_LEN; NameIndex++ )
{
if ( OmfFileName[ NameIndex ] != POmfDirEnt->FolderName[ NameIndex ] )
{
return FALSE;
}
}
//
// check extension
//
if ( OmfType != POmfDirEnt->FolderType )
{
return FALSE;
}
//
// all done, return ok
//
return TRUE;
}
// ----------------------------------------------------------------------------
// PROCEDURE: OmfHeaderValidate:
//
// DESCRIPTION: The routine checks if the specified OMF header data is valid.
//
// ARGUMENTS: FileId file table entry index
//
// RETURN: TRUE is returned if file is ok.
// FALSE is returned if file is not correct.
//
// ASSUMPTIONS: The header data has already been copied in the
// context data of the file table entry.
// The size of all the OMF structures is a multiple of a word.
//
// CALLS:
//
// GLOBALS:
//
// NOTES:
// ----------------------------------------------------------------------------
//
BOOLEAN
OmfHeaderValidate
(
IN ULONG FileId
)
{
//
// local variables
//
POMF_HDR POmfHeader; // pointer to the header data
ULONG OmfDirLink; // directory link in words
ULONG OmfDirLength; // directory size in words
ULONG OmfSize; // OMF size in bytes
UCHAR Checksum=0; // used to compute the checksum
PRINTDBG("OmfHeaderValidate\n\r");
//
// initialize variables
//
POmfHeader = &BlFileTable[FileId].u.OmfHeaderContext.OmfHeader;
OmfDirLink = POmfHeader->FolderDirectoryLink;
OmfDirLength =(POmfHeader->FolderCount * sizeof(OMF_DIR_ENT))/(1<<WORD_2P2);
OmfSize = (ULONG)POmfHeader->FwSize * OMF_BLOCK_SIZE;
if (!OmfSize)
{
OmfSize = OMF_MAX_SIZE;
}
//
// check header values
//
if ( POmfHeader->ID[0] != OMF_ID_1ST
||
POmfHeader->ID[1] != OMF_ID_2ND
||
POmfHeader->ID[2] != OMF_ID_3RD
||
POmfHeader->ID[3] != OMF_ID_4TH
||
!isalnum(POmfHeader->FwVersion)
||
!isalnum(POmfHeader->FwRevision)
||
sizeof(OMF_HDR) > OmfSize
||
OmfDirLink + OmfDirLength > OmfSize/(1<<WORD_2P2)
||
FwFileIdChecksum( FileId,
RtlConvertUlongToLargeInteger(0l),
(ULONG)(sizeof(OMF_HDR)),
&Checksum )
||
FwFileIdChecksum( FileId,
RtlConvertUlongToLargeInteger(OmfDirLink<<WORD_2P2),
OmfDirLength << WORD_2P2,
&Checksum )
// >>> FIXME <<<
// ||
// Checksum
)
{
return FALSE;
}
else
{
return TRUE;
}
}
// ----------------------------------------------------------------------------
// PROCEDURE: OmfFileValidate:
//
// DESCRIPTION: The routine checks if the selected file is valid.
//
// ARGUMENTS: FileId file table entry index
//
// RETURN: TRUE is returned if file is ok.
// FALSE is returned if file is not correct.
//
// ASSUMPTIONS: the folder name and its extension (type) have already
// been validated.
//
// CALLS:
//
// GLOBALS:
//
// NOTES:
// ----------------------------------------------------------------------------
//
BOOLEAN
OmfFileValidate
(
IN ULONG FileId
)
{
//
// local variables
//
POMF_DIR_ENT POmfDirEnt; // OMF directory entry pointer
ULONG OmfFileLength; // file length, word count
ULONG OmfFileLink; // file link, word count
ULONG DeviceId; // device id file table entry
ULONG OmfLength; // OMF rom length, word count
UCHAR Checksum=0; // used to compute the checksum
PRINTDBG("OmfFileValidate\n\r");
//
// initialize variables
//
POmfDirEnt = &BlFileTable[FileId].u.OmfFileContext.OmfDirEnt;
OmfFileLink = POmfDirEnt->FolderLink;
OmfFileLength = POmfDirEnt->FolderSize;
DeviceId = BlFileTable[FileId].DeviceId;
OmfLength=(ULONG)BlFileTable[DeviceId].u.OmfHeaderContext.OmfHeader.FwSize *
OMF_BLOCK_SIZE/(1<<WORD_2P2);
if (!OmfLength)
{
OmfLength = OMF_MAX_SIZE/(1<<WORD_2P2);
}
//
// validate file
//
if ( OmfFileLink > OMF_MAX_FILE_LINK
||
OmfFileLength > OMF_MAX_FILE_LEN
||
OmfFileLink + OmfFileLength > OmfLength
||
FwFileIdChecksum( DeviceId,
RtlConvertUlongToLargeInteger(OmfFileLink<<WORD_2P2),
OmfFileLength << WORD_2P2,
&Checksum )
// >>> FIXME <<<
// ||
// (Checksum += POmfDirEnt->FolderChecksumByte)
)
{
return FALSE;
}
else
{
return TRUE;
}
}
// ----------------------------------------------------------------------------
// PROCEDURE: ConvertOmfDirToArcDir:
//
// DESCRIPTION: The routine converts the OMF directory entry in the ARC
// directory entry format.
//
// ARGUMENTS: OmfFileBuffer pointer to OMF directory entry
// DirEntry pointer to ARC directory entry to be filled
//
// RETURN: NONE
//
// ASSUMPTIONS: FileNameLengthMax is at least 3 chars.
//
// CALLS:
//
// GLOBALS:
//
// NOTES:
// ----------------------------------------------------------------------------
//
VOID
ConvertOmfDirToArcDir
(
IN POMF_DIR_ENT POmfDirEnt,
OUT DIRECTORY_ENTRY *PArcDirEnt
)
{
//
// local variables
//
ULONG CharIndex; // name+extension length
ULONG MaxFileName; // max name length
PRINTDBG("ConvertOmfDirToArcDir\n\r");
//
// set attribute bit (read only file)
//
PArcDirEnt->FileAttribute = ArcReadOnlyFile;
//
// set file name (note that 3 means: '.' + extension + '\0' )
//
MaxFileName = MIN( 32 - 3, OMF_FILE_NAME_LEN );
for ( CharIndex = 0;
CharIndex < MaxFileName && POmfDirEnt->FolderName[ CharIndex ];
CharIndex++ )
{
PArcDirEnt->FileName[ CharIndex ] = POmfDirEnt->FolderName[ CharIndex];
}
//
// dot '.'
//
PArcDirEnt->FileName[ CharIndex++ ] = '.';
//
// extension
//
PArcDirEnt->FileName[ CharIndex++ ] = POmfDirEnt->FolderType;
//
// null char
//
PArcDirEnt->FileName[ CharIndex ]='\0';
//
// set length (note: CharIndex is 0-based)
//
PArcDirEnt->FileNameLength = CharIndex;
//
// all done, exit.
//
return;
}
// ----------------------------------------------------------------------------
// PROCEDURE: FwGetEisaId:
//
// DESCRIPTION: The routine returns the requested board and info id.
//
// ARGUMENTS: PathName Option board path name pointer
// EisaId Pointer to 7 bytes space for the id
// IdInfo Pointer to 1 byte space for the info id
//
// RETURN: TRUE all done.
// FALSE for any error.
//
// ASSUMPTIONS:
//
// CALLS:
//
// GLOBALS:
//
// NOTES:
// ----------------------------------------------------------------------------
//
BOOLEAN
FwGetEisaId
(
IN PCHAR PathName,
OUT PCHAR EisaId,
OUT PUCHAR IdInfo
)
{
//
// define local variables
//
PCONFIGURATION_COMPONENT pComp; // Pointer to a component struc
EISA_SLOT_INFO SlotInfo; // pointer to first eisa info
BOOLEAN GetIdStatus = FALSE; // be pessimistic
PRINTDBG("FwGetEisaId\n\r"); // DEBUG SUPPORT
//
// Check to see if the motherboard component is being accessed. Since
// Jensen doesn't have a motherboard id, substitute values.
//
if (strstr(PathName, "eisa(0)other(0)") != NULL) {
EisaId[0] = 'J';
EisaId[1] = 'e';
EisaId[2] = 'n';
EisaId[3] = 's';
EisaId[4] = 'e';
EisaId[5] = 'n';
EisaId[6] = '0';
*IdInfo = 0;
GetIdStatus = TRUE;
//
// get the requested component
//
} else if ( (pComp = FwGetComponent(PathName)) == NULL );
//
// check the configuration data length
//
else if ( pComp->ConfigurationDataLength < EISA_SLOT_MIN_INFO );
//
// get the slot info
//
else if ( FwGetConfigurationDataIndex( (PVOID)&SlotInfo,
pComp,
CONFIGDATAHEADER_SIZE,
EISA_SLOT_INFO_SIZE ));
//
// get the requested info
//
else
{
FwUncompressEisaId( &SlotInfo.Id1stChar, EisaId );
*IdInfo = SlotInfo.IdInfo;
GetIdStatus = TRUE;
}
//
// return status
//
return GetIdStatus;
}
// ----------------------------------------------------------------------------
// PROCEDURE: FwUncompressEisaId:
//
// DESCRIPTION: The routine converts the specified compressed ID in 7 ASCII
// chars.
//
// ARGUMENTS: CompEisaId Pointer to the compressed ID (4 bytes)
// UncompEisaId Pointer to the uncompressed ID (7 bytes)
//
// RETURN: none
//
// ASSUMPTIONS: Compressed ID : 1st byte bit 7 - Reserved
// bits 6-2 - 1st char name comp
// bits 1-0 - 2nd char name comp
// 2nd byte bits 7-5 - 2nd char name
// bits 4-0 - 3rd char name comp
// 3rd byte bits 7-4 - 1st decimal number comp
// bits 3-0 - 2nd decimal number comp
// 4th byte bits 7-4 - 3rd decimal number comp
// bits 3-0 - 4th decimal number comp
//
// Uncompressed ID: 1st byte 1st char name
// 2nd byte 2nd char name
// 3rd byte 3rd char name
// 4th byte 1st decimal number
// 5th byte 2nd decimal number
// 6th byte 3rd decimal number
// 7th byte 4th decimal number
//
// Compressed -> Uncompressed :
//
// char comp + 'A' - 1 = char uncompressed
// decimal comp + '0' = decimal uncompressed
//
//
// CALLS:
//
// GLOBALS:
//
// NOTES:
// ----------------------------------------------------------------------------
//
VOID
FwUncompressEisaId
(
IN PUCHAR CompEisaId,
OUT PUCHAR UncompEisaId
)
{
//
// local variables
//
ULONG Id; // used to hold the 4 bytes ID
SHORT i; // general index
UCHAR d; // hexadecimal digit
PRINTDBG("FwUncompressEisaId\n\r");
//
// transform the 4 chars ID in a ULONG
//
Id = Fw4UcharToUlongMSB( CompEisaId );
//
// uncompress 4 digits, starting from the last one
//
for (i=3; i>=0; i--)
{
d = Id & ID_DIGIT_MASK;
UncompEisaId[3+i] = (d <= 9) ? (d + '0') : (d - 0xA + 'A');
Id >>= ID_DIGIT_SIZE;
}
//
// uncompress 3 chars
//
for (i=2; i>=0; i--)
{
UncompEisaId[i] = (Id & ID_CHAR_MASK) + 'A' - 1;
Id >>= ID_CHAR_SIZE;
}
//
// exit
//
return;
}
// ----------------------------------------------------------------------------
// PROCEDURE: FwGetEisaBusIoCpuAddress:
//
// DESCRIPTION: The routine returns the virtual (CPU) address for the specified
// EISA bus.
//
// ARGUMENTS: EisaPath pointer to the path string
// IoBusAddress pointer to a PVOID variable. It used to store
// the computed address.
//
// RETURN: TRUE returned if all correct.
// FALSE returned for any error.
//
// ASSUMPTIONS:
//
// CALLS:
//
// GLOBALS:
//
// NOTES:
// ----------------------------------------------------------------------------
//
BOOLEAN
FwGetEisaBusIoCpuAddress
(
IN PCHAR EisaPath,
OUT PVOID *IoBusAddress
)
{
//
// define local variables
//
PCONFIGURATION_COMPONENT PComponent;
EISA_ADAPTER_DETAILS EisaInfo;
PRINTDBG("FwGetEisaBusIoCpuAddress\n\r");
//
// get the requested component and configuration data
//
if ( (PComponent = FwGetComponent( EisaPath )) == NULL ||
FwGetConfigurationData( (PVOID)&EisaInfo, PComponent ))
{
return FALSE;
}
//
// Return the requested virtual (CPU) address
//
*IoBusAddress = EisaInfo.IoStart;
return TRUE;
}
// ----------------------------------------------------------------------------
// PROCEDURE: FwFileChecksum:
//
// DESCRIPTION: The routine performs a byte checksum on the specified file.
//
// ARGUMENTS: Path File path
// Checksum File checksum
//
// RETURN: ESUCCESS Operation completed successfully.
// ...other Error code.
//
// ASSUMPTIONS: none
//
// CALLS: FwFileIdChecksum
//
// GLOBALS: none
//
// NOTES: The file length must be contained in a ULONG (4G -1).
// ----------------------------------------------------------------------------
//
ARC_STATUS
FwFileChecksum
(
IN PCHAR Path,
OUT PUCHAR Checksum
)
{
ARC_STATUS Status;
ULONG FileId;
FILE_INFORMATION FileInfo;
//
// initialize checksum to zero
//
*Checksum = 0;
//
// open file
//
if (Status = FwOpen( Path, ArcOpenReadOnly, &FileId ))
{
return Status;
}
//
// get file information
//
if (Status = FwGetFileInformation( FileId, &FileInfo ));
//
// return an error if file is greater than 4G - 1
//
else if (FileInfo.EndingAddress.HighPart != 0)
{
Status = EINVAL;
}
//
// perform the checksum and return the status
//
else
{
Status = FwFileIdChecksum( FileId,
FileInfo.StartingAddress,
FileInfo.EndingAddress.LowPart,
Checksum );
}
//
// clase file and return status
//
FwClose( FileId );
return Status;
}
// ----------------------------------------------------------------------------
// PROCEDURE: FwChecksumByte:
//
// DESCRIPTION: The routine performs a byte checksum on the specified buffer.
//
// ARGUMENTS: Buffer Pointer to area to checksum.
// Length Length of area to checksum (bytes).
// ChecksumByte The pointed byte is used in input as a
// starting checksum value and in output as
// the final checksum value.
//
// RETURN: ESUCCESS operation completed successfully
//
// ASSUMPTIONS: none
//
// CALLS: none
//
// GLOBALS: none
//
// NOTES: none
//
// ----------------------------------------------------------------------------
//
ARC_STATUS
FwChecksumByte (
IN PUCHAR Buffer,
IN ULONG Length,
IN OUT PUCHAR ChecksumByte
)
{
//
// checksum the buffer and exit
//
while (Length--)
{
*ChecksumByte += *Buffer++;
}
return ESUCCESS;
}
// ----------------------------------------------------------------------------
// PROCEDURE: FwFileIdChecksum:
//
// DESCRIPTION: The routine performs a byte checksum within the spcified
// range of the FileId.
//
// ARGUMENTS: FileId File table entry index.
// StartingOffset Beginning of checksum range (byte offset).
// Length Number of bytes to checksum.
// Checksum Input : start checksum value
// Output: image checksum
//
// RETURN: ESUCCESS Operation completed successfully.
// ...other Error code.
//
// ASSUMPTIONS: none
//
// CALLS: FwChecksumByte
//
// GLOBALS: none
//
// NOTES: This routine can also be called during the "open" phase
// (the open bit is not set), because the read and seek functions
// are called directly using the table within the file id
// descriptor.
// ----------------------------------------------------------------------------
//
ARC_STATUS
FwFileIdChecksum
(
IN ULONG FileId,
IN LARGE_INTEGER StartingOffset,
IN ULONG Length,
IN OUT PUCHAR Checksum
)
{
ARC_STATUS Status;
ULONG BytesToRead;
ULONG Count;
UCHAR TempBuffer[MAXIMUM_SECTOR_SIZE + MAX_DCACHE_LINE_SIZE];
PUCHAR TempPointer = ALIGN_BUFFER( TempBuffer );
//
// If buffer length is zero, return ESUCCESS
//
if (Length==0)
{
return ESUCCESS;
}
//
// position the file pointer
//
if (Status = (BlFileTable[FileId].DeviceEntryTable->Seek)
(FileId, &StartingOffset, SeekAbsolute))
{
return Status;
}
//
// perform the checksum
//
do
{
BytesToRead = MIN( Length, MAXIMUM_SECTOR_SIZE );
//
// fill the buffer
//
if (Status = (BlFileTable[FileId].DeviceEntryTable->Read)
(FileId, TempPointer, BytesToRead, &Count))
{
return Status;
}
//
// make sure that we got the requested number of bytes
//
if (Count != BytesToRead)
{
return EINVAL;
}
//
// checksum the area
//
FwChecksumByte( TempPointer, BytesToRead, Checksum);
} while ( Length -= BytesToRead );
//
// all done
//
return Status;
}
// ----------------------------------------------------------------------------
// PROCEDURE: FwGetMnemonicKey;
//
// DESCRIPTION: The routine returns the specified key. The specified key
// within the path string must be in digits, an error is returned
// otherwise.
//
// ARGUMENTS: Path pointer to the pathname string
// Mnemonic mnemonic string
// Key pointer to buffer used to hold the ouput
//
// RETURN: TRUE returned if all correct
// FALSE returned invalid input parameter
//
// ASSUMPTIONS:
//
// CALLS:
//
// GLOBALS:
//
// NOTES:
// ----------------------------------------------------------------------------
//
BOOLEAN
FwGetMnemonicKey
(
IN PCHAR Path,
IN PCHAR Mnemonic,
IN PULONG Key
)
{
PCHAR Tmp;
PCHAR Tmp2;
CHAR Digits[ KEY_MAX_DIGITS + 1 ];
ULONG i;
CHAR String[ MAX_MNEMONIC_LEN + 3 ]; // mnemonic + ')' + '(' + '\0'
PRINTDBG("FwGetMnemonicKey\n\r");
//
// Construct a string of the form ")mnemonic("
//
String[0]=')';
for(i=1; *Mnemonic; i++)
{
String[i] = * Mnemonic++;
}
String[i++]='(';
String[i]='\0';
//
// first look for the "mnemonic(" string.
//
if ( (Tmp = strstr( Path, &String[1] )) == NULL)
{
return FALSE;
}
//
// if not the begin of the path name, look for the ")mnemonic(" string.
//
if (Tmp != Path)
{
if ( (Tmp = strstr( Path, String )) == NULL)
{
return FALSE;
}
}
else
{
i--;
}
//
// skip the mnemonic
//
Tmp+=i;
//
// make sure that the number of digits is within the allowed range
//
if ((Tmp2 = strchr(Tmp, ')')) == NULL || Tmp2 - Tmp > KEY_MAX_DIGITS )
{
return FALSE;
}
//
// convert the value in between parentesis to integer
//
for ( i=0; *Tmp != ')'; i++ )
{
if ( !isdigit( Digits[i] = *Tmp++ ))
{
return FALSE;
}
}
Digits[i]='\0';
//
// return the converted number
//
*Key = i ? atoi(Digits) : 0;
return TRUE;
}
// ----------------------------------------------------------------------------
// PROCEDURE: FwGetNextMnemonic:
//
// DESCRIPTION: The routine returns the next mnemonic in the list.
// If Mnemonic is a null string, the first mnemonic of the list
// is returned. The FALSE value is returned if the specified
// mnemonic is not present or end of list.
//
//
// ARGUMENTS: Path pointer to the pathname string.
// Mnemonic mnemonic string pointer
// NextMnemonic next mnemonic string pointer
//
// RETURN: TRUE returned if all correct
// FALSE returned if invalid input parameter or end of
// list
//
// ASSUMPTIONS: The path is composed by ARC mnemonic names as follows:
// adapter(.)..adapter(.)controller(.)peripheral(.)'\0'.
// The NextMnemonic string is big enough to hold the mnemonic
// name.
//
// CALLS:
//
// GLOBALS:
//
// NOTES:
// ----------------------------------------------------------------------------
//
BOOLEAN
FwGetNextMnemonic
(
IN PCHAR Path,
IN PCHAR Mnemonic,
OUT PCHAR NextMnemonic
)
{
//
// local variables
//
PCHAR Tmp = Path;
PCHAR Tmp2;
ULONG i;
CHAR String[ MAX_MNEMONIC_LEN + 3 ]; // mnemonic + ')' + '(' + '\0'
PRINTDBG("FwGetNextMnemonic\n\r");
if ( *Mnemonic )
{
//
// Construct a string of the form ")mnemonic("
//
String[0]=')';
for(i=1; *Mnemonic; i++)
{
String[i] = *Mnemonic++;
}
String[i++]='(';
String[i]='\0';
//
// first look for the "mnemonic(" string.
//
if ( (Tmp = strstr( Path, &String[1] )) == NULL)
{
return FALSE;
}
//
// if not the begin of the path name, look for the ")mnemonic(" string.
//
if (Tmp != Path)
{
if ( (Tmp = strstr( Path, String )) == NULL)
{
return FALSE;
}
Tmp++;
}
//
// return an error if there is another mnemonic with same name
//
if (strstr( Tmp, String ) != NULL)
{
return FALSE;
}
//
// find the start of the next mnemonic
//
if ( (Tmp = strchr(Tmp,')')) == NULL )
{
return FALSE;
}
Tmp++;
}
//
// find the end of the next mnemonic and copy it.
//
if ( (Tmp2 = strchr(Tmp,'(')) == NULL || Tmp2 == Tmp ||
strchr( Tmp2, ')') == NULL )
{
return FALSE;
}
//
// copy the mnemonic
//
while( Tmp < Tmp2 )
{
*NextMnemonic++ = *Tmp++;
}
*NextMnemonic = '\0';
//
// return all done
//
return TRUE;
}
// ----------------------------------------------------------------------------
// PROCEDURE: FwGetMnemonicPath:
//
// DESCRIPTION: The routine returns a pointer to the mnemonic path.
// The routine uses the first mnemoic match to built
// the mnemonic path.
//
// ARGUMENTS: Path pointer to the path string.
// Mnemonic pointer to the mnemomic.
// MnemonicPath pointer to the mnemonic path string.
//
// RETURN: TRUE returned if all correct.
// FALSE returned for any error.
//
// ASSUMPTIONS: the string pointed by MnemonicPath must be enough large to
// contain the mnemoinc path.
//
// CALLS:
//
// GLOBALS:
//
// NOTES:
// ----------------------------------------------------------------------------
//
BOOLEAN
FwGetMnemonicPath
(
IN PCHAR Path,
IN PCHAR Mnemonic,
OUT PCHAR MnemonicPath
)
{
//
// local variables
//
PCHAR Tmp;
ULONG i;
CHAR String[ MAX_MNEMONIC_LEN + 3 ]; // mnemonic + ')' + '(' + '\0'
PRINTDBG("FwGetMnemonicPath\n\r");
//
// Construct a string of the form ")mnemonic("
//
String[0]=')';
for(i=1; *Mnemonic; i++)
{
String[i] = *Mnemonic++;
}
String[i++]='(';
String[i]='\0';
//
// first look for the "mnemonic(" string.
//
if ( (Tmp = strstr( Path, &String[1] )) == NULL)
{
return FALSE;
}
//
// if not the begin of the path name, look for the ")mnemonic(" string.
//
if (Tmp != Path)
{
if ( (Tmp = strstr( Path, String )) == NULL)
{
return FALSE;
}
Tmp++;
}
//
// find the end of this mnemonic
//
if ( (Tmp = strchr(Tmp,')')) == NULL )
{
return FALSE;
}
//
// copy the mnemonic path in the output string
//
strncpy( MnemonicPath, Path, Tmp-Path+1 );
MnemonicPath[ Tmp-Path+1 ] = '\0';
//
// all done, return
//
return TRUE;
}
// ----------------------------------------------------------------------------
// PROCEDURE: GetNextPath:
//
// DESCRIPTION: The routine isolates the first path string entry form the
// specified path string list.
//
// ARGUMENTS: PathList pointer to the path string list pointer.
// it is updated upon return to point the
// next path string entry.
// PathTarget pointer to the isolated path string.
//
//
// RETURN: TRUE returned if operation is successful.
// FALSE returned if end of list has been reached.
//
// ASSUMPTIONS: The path string list is ended with a null char ('\0') and
// the path string entries are separated from each other with
// the ';' char.
// The target string has enough space to hold the isolated
// path string.
//
// CALLS:
//
// GLOBALS:
//
// NOTES:
// ----------------------------------------------------------------------------
//
BOOLEAN
GetNextPath
(
IN OUT PCHAR *PPathList,
OUT PCHAR PathTarget
)
{
PRINTDBG("GetNextPath\n\r");
//
// if end of list, retrun with error
//
if (!**PPathList)
{
return FALSE;
}
//
// copy the path string and update the pointer
//
for (; *PathTarget=**PPathList; *PathTarget++, *(*PPathList)++)
{
if (**PPathList==';')
{
*PathTarget='\0';
(*PPathList)++;
break;
}
}
return TRUE;
}