summaryrefslogtreecommitdiffstats
path: root/private/ntos/fw/mips/omf.c
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/fw/mips/omf.c
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/ntos/fw/mips/omf.c')
-rw-r--r--private/ntos/fw/mips/omf.c3791
1 files changed, 3791 insertions, 0 deletions
diff --git a/private/ntos/fw/mips/omf.c b/private/ntos/fw/mips/omf.c
new file mode 100644
index 000000000..67cbc466e
--- /dev/null
+++ b/private/ntos/fw/mips/omf.c
@@ -0,0 +1,3791 @@
+// ----------------------------------------------------------------------------
+//
+// 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,
+ 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,
+ 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_REGISTER_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;
+ }
+ }
+
+ //
+ // 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 upgrate 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_REGISTER_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_REGISTER_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_REGISTER_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
+ // Jazz doesn't have a motherboard id, substitute values.
+ //
+
+ if (strstr(PathName, "eisa(0)other(0)") != NULL) {
+ EisaId[0] = 'J';
+ EisaId[1] = 'A';
+ EisaId[2] = 'Z';
+ EisaId[3] = '0';
+ EisaId[4] = '0';
+ EisaId[5] = '0';
+ 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;
+}
+
+
+
+