987 lines
24 KiB
C
987 lines
24 KiB
C
/*++
|
||
|
||
Copyright (c) 1991 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
blconfig.c
|
||
|
||
Abstract:
|
||
|
||
This module implements the OS loader configuration initialization.
|
||
|
||
Author:
|
||
|
||
David N. Cutler (davec) 9-Sep-1991
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
#include "bootlib.h"
|
||
#include "stdio.h"
|
||
#include "stdlib.h"
|
||
|
||
ULONG
|
||
BlMatchToken (
|
||
IN PCHAR TokenValue,
|
||
IN CHAR * FIRMWARE_PTR TokenArray[]
|
||
);
|
||
|
||
PCHAR
|
||
BlGetNextToken (
|
||
IN PCHAR TokenString,
|
||
OUT PCHAR OutputToken,
|
||
OUT PULONG UnitNumber
|
||
);
|
||
|
||
//
|
||
// Define types of adapters that can be booted from.
|
||
//
|
||
|
||
typedef enum _ADAPTER_TYPES {
|
||
AdapterEisa,
|
||
AdapterScsi,
|
||
AdapterMulti,
|
||
AdapterNet,
|
||
AdapterRamdisk,
|
||
AdapterMaximum
|
||
} ADAPTER_TYPES;
|
||
|
||
//
|
||
// Define type of controllers that can be booted from.
|
||
//
|
||
|
||
typedef enum _CONTROLLER_TYPES {
|
||
ControllerDisk,
|
||
ControllerCdrom,
|
||
ControllerMaximum
|
||
} CONTROLLER_TYPES;
|
||
|
||
//
|
||
// Define type of peripheral that can be booted from.
|
||
//
|
||
|
||
typedef enum _PERIPHERAL_TYPES {
|
||
PeripheralRigidDisk,
|
||
PeripheralFloppyDisk,
|
||
#if defined(ELTORITO)
|
||
PeripheralElTorito,
|
||
#endif
|
||
PeripheralMaximum
|
||
} PERIPHERAL_TYPES;
|
||
|
||
//
|
||
// Define the ARC pathname mnemonics.
|
||
//
|
||
|
||
CHAR * FIRMWARE_PTR MnemonicTable[] = {
|
||
"arc",
|
||
"cpu",
|
||
"fpu",
|
||
"pic",
|
||
"pdc",
|
||
"sic",
|
||
"sdc",
|
||
"sc",
|
||
"eisa",
|
||
"tc",
|
||
"scsi",
|
||
"dti",
|
||
"multi",
|
||
"disk",
|
||
"tape",
|
||
"cdrom",
|
||
"worm",
|
||
"serial",
|
||
"net",
|
||
"video",
|
||
"par",
|
||
"point",
|
||
"key",
|
||
"audio",
|
||
"other",
|
||
"rdisk",
|
||
"fdisk",
|
||
"tape",
|
||
"modem",
|
||
"monitor",
|
||
"print",
|
||
"pointer",
|
||
"keyboard",
|
||
"term",
|
||
"other"
|
||
};
|
||
|
||
CHAR * FIRMWARE_PTR BlAdapterTypes[AdapterMaximum + 1] = {"eisa","scsi","multi","net","ramdisk",NULL};
|
||
CHAR * FIRMWARE_PTR BlControllerTypes[ControllerMaximum + 1] = {"disk","cdrom",NULL};
|
||
#if defined(ELTORITO)
|
||
CHAR * FIRMWARE_PTR BlPeripheralTypes[PeripheralMaximum + 1] = {"rdisk","fdisk","cdrom",NULL};
|
||
#else
|
||
CHAR * FIRMWARE_PTR BlPeripheralTypes[PeripheralMaximum + 1] = {"rdisk","fdisk",NULL};
|
||
#endif
|
||
|
||
|
||
ARC_STATUS
|
||
BlConfigurationInitialize (
|
||
IN PCONFIGURATION_COMPONENT Parent,
|
||
IN PCONFIGURATION_COMPONENT_DATA ParentEntry
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine traverses the firmware configuration tree from the specified
|
||
parent entry and constructs the corresponding NT configuration tree.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
ESUCCESS is returned if the initialization is successful. Otherwise,
|
||
an unsuccessful status that describes the error is returned.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
PCONFIGURATION_COMPONENT Child;
|
||
PCONFIGURATION_COMPONENT_DATA ChildEntry;
|
||
PCHAR ConfigurationData;
|
||
PCONFIGURATION_COMPONENT_DATA PreviousSibling;
|
||
PCONFIGURATION_COMPONENT Sibling;
|
||
PCONFIGURATION_COMPONENT_DATA SiblingEntry;
|
||
ARC_STATUS Status;
|
||
|
||
//
|
||
// Traverse the child configuration tree and allocate, initialize, and
|
||
// construct the corresponding NT configuration tree.
|
||
//
|
||
|
||
Child = ArcGetChild(Parent);
|
||
while (Child != NULL) {
|
||
|
||
//
|
||
// Allocate an entry of the appropriate size to hold the child
|
||
// configuration information.
|
||
//
|
||
|
||
ChildEntry = (PCONFIGURATION_COMPONENT_DATA)BlAllocateHeap(
|
||
sizeof(CONFIGURATION_COMPONENT_DATA) +
|
||
Child->IdentifierLength +
|
||
Child->ConfigurationDataLength);
|
||
|
||
if (ChildEntry == NULL) {
|
||
return ENOMEM;
|
||
}
|
||
|
||
//
|
||
// Initialize the tree pointers and copy the component data.
|
||
//
|
||
|
||
if (ParentEntry == NULL) {
|
||
BlLoaderBlock->ConfigurationRoot = ChildEntry;
|
||
|
||
} else {
|
||
ParentEntry->Child = ChildEntry;
|
||
}
|
||
|
||
ChildEntry->Parent = ParentEntry;
|
||
ChildEntry->Sibling = NULL;
|
||
ChildEntry->Child = NULL;
|
||
RtlMoveMemory((PVOID)&ChildEntry->ComponentEntry,
|
||
(PVOID)Child,
|
||
sizeof(CONFIGURATION_COMPONENT));
|
||
|
||
ConfigurationData = (PCHAR)(ChildEntry + 1);
|
||
|
||
//
|
||
// If configuration data is specified, then copy the configuration
|
||
// data.
|
||
//
|
||
|
||
if (Child->ConfigurationDataLength != 0) {
|
||
ChildEntry->ConfigurationData = (PVOID)ConfigurationData;
|
||
Status = ArcGetConfigurationData((PVOID)ConfigurationData,
|
||
Child);
|
||
|
||
if (Status != ESUCCESS) {
|
||
return Status;
|
||
}
|
||
|
||
ConfigurationData += Child->ConfigurationDataLength;
|
||
|
||
} else {
|
||
ChildEntry->ConfigurationData = NULL;
|
||
}
|
||
|
||
//
|
||
// If identifier data is specified, then copy the identifier data.
|
||
//
|
||
|
||
if (Child->IdentifierLength !=0) {
|
||
ChildEntry->ComponentEntry.Identifier = ConfigurationData;
|
||
RtlMoveMemory((PVOID)ConfigurationData,
|
||
(PVOID)Child->Identifier,
|
||
Child->IdentifierLength);
|
||
|
||
} else {
|
||
ChildEntry->ComponentEntry.Identifier = NULL;
|
||
}
|
||
|
||
//
|
||
// Traverse the sibling configuration tree and allocate, initialize,
|
||
// and construct the corresponding NT configuration tree.
|
||
//
|
||
|
||
PreviousSibling = ChildEntry;
|
||
Sibling = ArcGetPeer(Child);
|
||
while (Sibling != NULL) {
|
||
|
||
//
|
||
// Allocate an entry of the appropriate size to hold the sibling
|
||
// configuration information.
|
||
//
|
||
|
||
SiblingEntry = (PCONFIGURATION_COMPONENT_DATA)BlAllocateHeap(
|
||
sizeof(CONFIGURATION_COMPONENT_DATA) +
|
||
Sibling->IdentifierLength +
|
||
Sibling->ConfigurationDataLength);
|
||
|
||
if (SiblingEntry == NULL) {
|
||
return ENOMEM;
|
||
}
|
||
|
||
//
|
||
// Initialize the tree pointers and copy the component data.
|
||
//
|
||
|
||
SiblingEntry->Parent = ParentEntry;
|
||
SiblingEntry->Sibling = NULL;
|
||
ChildEntry->Child = NULL;
|
||
RtlMoveMemory((PVOID)&SiblingEntry->ComponentEntry,
|
||
(PVOID)Sibling,
|
||
sizeof(CONFIGURATION_COMPONENT));
|
||
|
||
ConfigurationData = (PCHAR)(SiblingEntry + 1);
|
||
|
||
//
|
||
// If configuration data is specified, then copy the configuration
|
||
// data.
|
||
//
|
||
|
||
if (Sibling->ConfigurationDataLength != 0) {
|
||
SiblingEntry->ConfigurationData = (PVOID)ConfigurationData;
|
||
Status = ArcGetConfigurationData((PVOID)ConfigurationData,
|
||
Sibling);
|
||
|
||
if (Status != ESUCCESS) {
|
||
return Status;
|
||
}
|
||
|
||
ConfigurationData += Sibling->ConfigurationDataLength;
|
||
|
||
} else {
|
||
SiblingEntry->ConfigurationData = NULL;
|
||
}
|
||
|
||
//
|
||
// If identifier data is specified, then copy the identifier data.
|
||
//
|
||
|
||
if (Sibling->IdentifierLength !=0) {
|
||
SiblingEntry->ComponentEntry.Identifier = ConfigurationData;
|
||
RtlMoveMemory((PVOID)ConfigurationData,
|
||
(PVOID)Sibling->Identifier,
|
||
Sibling->IdentifierLength);
|
||
|
||
} else {
|
||
SiblingEntry->ComponentEntry.Identifier = NULL;
|
||
}
|
||
|
||
//
|
||
// If the sibling has a child, then generate the tree for the
|
||
// child.
|
||
//
|
||
|
||
if (ArcGetChild(Sibling) != NULL) {
|
||
Status = BlConfigurationInitialize(Sibling, SiblingEntry);
|
||
if (Status != ESUCCESS) {
|
||
return Status;
|
||
}
|
||
}
|
||
|
||
//
|
||
// Set new sibling pointers and get the next sibling tree entry.
|
||
//
|
||
|
||
PreviousSibling->Sibling = SiblingEntry;
|
||
PreviousSibling = SiblingEntry;
|
||
Sibling = ArcGetPeer(Sibling);
|
||
}
|
||
|
||
//
|
||
// Set new parent pointers and get the next child tree entry.
|
||
//
|
||
|
||
Parent = Child;
|
||
ParentEntry = ChildEntry;
|
||
Child = ArcGetChild(Child);
|
||
}
|
||
|
||
return ESUCCESS;
|
||
}
|
||
|
||
|
||
|
||
BOOLEAN
|
||
BlSearchConfigTree(
|
||
IN PCONFIGURATION_COMPONENT_DATA Node,
|
||
IN CONFIGURATION_CLASS Class,
|
||
IN CONFIGURATION_TYPE Type,
|
||
IN ULONG Key,
|
||
IN PNODE_CALLBACK CallbackRoutine
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Conduct a depth-first search of the firmware configuration tree starting
|
||
at a given node, looking for nodes that match a given class and type.
|
||
When a matching node is found, call a callback routine.
|
||
|
||
Arguments:
|
||
|
||
CurrentNode - node at which to begin the search.
|
||
|
||
Class - configuration class to match, or -1 to match any class
|
||
|
||
Type - configuration type to match, or -1 to match any class
|
||
|
||
Key - key to match, or -1 to match any key
|
||
|
||
FoundRoutine - pointer to a routine to be called when a node whose
|
||
class and type match the class and type passed in is located.
|
||
The routine takes a pointer to the configuration node and must
|
||
return a boolean indicating whether to continue with the traversal.
|
||
|
||
Return Value:
|
||
|
||
FALSE if the caller should abandon the search.
|
||
--*/
|
||
{
|
||
PCONFIGURATION_COMPONENT_DATA Child;
|
||
|
||
do {
|
||
if (Child = Node->Child) {
|
||
if (!BlSearchConfigTree(Child,
|
||
Class,
|
||
Type,
|
||
Key,
|
||
CallbackRoutine)) {
|
||
return(FALSE);
|
||
}
|
||
}
|
||
|
||
if (((Class == -1) || (Node->ComponentEntry.Class == Class))
|
||
&&((Type == -1) || (Node->ComponentEntry.Type == Type))
|
||
&&((Key == (ULONG)-1) || (Node->ComponentEntry.Key == Key))) {
|
||
|
||
if (!CallbackRoutine(Node)) {
|
||
return(FALSE);
|
||
}
|
||
}
|
||
|
||
Node = Node->Sibling;
|
||
|
||
} while ( Node != NULL );
|
||
|
||
return(TRUE);
|
||
}
|
||
|
||
|
||
VOID
|
||
BlGetPathnameFromComponent(
|
||
IN PCONFIGURATION_COMPONENT_DATA Component,
|
||
OUT PCHAR ArcName
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function builds an ARC pathname for the specified component.
|
||
|
||
Arguments:
|
||
|
||
Component - Supplies a pointer to a configuration component.
|
||
|
||
ArcName - Returns the ARC name of the specified component. Caller must
|
||
provide a large enough buffer.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
|
||
if (Component->Parent != NULL) {
|
||
BlGetPathnameFromComponent(Component->Parent,ArcName);
|
||
//
|
||
// append our segment to the arcname
|
||
//
|
||
|
||
sprintf(ArcName+strlen(ArcName),
|
||
"%s(%d)",
|
||
MnemonicTable[Component->ComponentEntry.Type],
|
||
Component->ComponentEntry.Key);
|
||
|
||
} else {
|
||
//
|
||
// We are the parent, initialize the string and return
|
||
//
|
||
ArcName[0] = '\0';
|
||
}
|
||
|
||
return;
|
||
}
|
||
|
||
|
||
BOOLEAN
|
||
BlGetPathMnemonicKey(
|
||
IN PCHAR OpenPath,
|
||
IN PCHAR Mnemonic,
|
||
IN PULONG Key
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine looks for the given Mnemonic in OpenPath.
|
||
If Mnemonic is a component of the path, then it converts the key
|
||
value to an integer wich is returned in Key.
|
||
|
||
Arguments:
|
||
|
||
OpenPath - Pointer to a string that contains an ARC pathname.
|
||
|
||
Mnemonic - Pointer to a string that contains a ARC Mnemonic
|
||
|
||
Key - Pointer to a ULONG where the Key value is stored.
|
||
|
||
|
||
Return Value:
|
||
|
||
FALSE if mnemonic is found in path and a valid key is converted.
|
||
TRUE otherwise.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
PCHAR Tmp;
|
||
CHAR Digits[9];
|
||
ULONG i;
|
||
CHAR String[16];
|
||
|
||
//
|
||
// Construct a string of the form ")mnemonic("
|
||
//
|
||
String[0]=')';
|
||
for(i=1;*Mnemonic;i++) {
|
||
String[i] = * Mnemonic++;
|
||
}
|
||
String[i++]='(';
|
||
String[i]='\0';
|
||
|
||
if ((Tmp=strstr(OpenPath,&String[1])) == NULL) {
|
||
return TRUE;
|
||
}
|
||
|
||
if (Tmp != OpenPath) {
|
||
if ((Tmp=strstr(OpenPath,String)) == NULL) {
|
||
return TRUE;
|
||
}
|
||
} else {
|
||
i--;
|
||
}
|
||
//
|
||
// skip the mnemonic and convert the value in between parentheses to integer
|
||
//
|
||
Tmp+=i;
|
||
for (i=0;i<sizeof(Digits) - 1;i++) {
|
||
if (*Tmp == ')') {
|
||
Digits[i] = '\0';
|
||
break;
|
||
}
|
||
Digits[i] = *Tmp++;
|
||
}
|
||
Digits[i]='\0';
|
||
*Key = atoi(Digits);
|
||
return FALSE;
|
||
}
|
||
|
||
|
||
ARC_STATUS
|
||
BlGenerateDeviceNames (
|
||
IN PCHAR ArcDeviceName,
|
||
OUT PCHAR ArcCanonicalName,
|
||
OUT OPTIONAL PCHAR NtDevicePrefix
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine generates an NT device name prefix and a canonical ARC
|
||
device name from an ARC device name.
|
||
|
||
Arguments:
|
||
|
||
ArcDeviceName - Supplies a pointer to a zero terminated ARC device
|
||
name.
|
||
|
||
ArcCanonicalName - Supplies a pointer to a variable that receives the
|
||
ARC canonical device name.
|
||
|
||
NtDevicePrefix - If present, supplies a pointer to a variable that receives the
|
||
NT device name prefix.
|
||
|
||
Return Value:
|
||
|
||
ESUCCESS is returned if an NT device name prefix and the canonical
|
||
ARC device name are successfully generated from the ARC device name.
|
||
Otherwise, an invalid argument status is returned.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
CHAR AdapterPath[64];
|
||
CHAR AdapterName[32];
|
||
ULONG AdapterNumber;
|
||
CHAR ControllerName[32];
|
||
ULONG ControllerNumber;
|
||
ULONG MatchIndex;
|
||
CHAR PartitionName[32];
|
||
ULONG PartitionNumber;
|
||
CHAR PeripheralName[32];
|
||
ULONG PeripheralNumber;
|
||
CHAR TokenValue[32];
|
||
|
||
//
|
||
// Get the adapter and make sure it is valid.
|
||
//
|
||
|
||
ArcDeviceName = BlGetNextToken(ArcDeviceName,
|
||
&AdapterName[0],
|
||
&AdapterNumber);
|
||
|
||
if (ArcDeviceName == NULL) {
|
||
return EINVAL;
|
||
}
|
||
|
||
MatchIndex = BlMatchToken(&AdapterName[0], &BlAdapterTypes[0]);
|
||
if (MatchIndex == AdapterMaximum) {
|
||
return EINVAL;
|
||
}
|
||
|
||
sprintf(AdapterPath, "%s(%d)", AdapterName, AdapterNumber);
|
||
if ((MatchIndex == AdapterNet) || (MatchIndex == AdapterRamdisk)) {
|
||
strcpy(ArcCanonicalName, AdapterPath);
|
||
if (ARGUMENT_PRESENT(NtDevicePrefix)) {
|
||
*NtDevicePrefix = 0;
|
||
}
|
||
return ESUCCESS;
|
||
}
|
||
|
||
//
|
||
// The next token is either another adapter or a controller. ARC
|
||
// names can have multiple adapters. (e.g. "multi(0)scsi(0)disk(0)...")
|
||
// Iterate until we find a token that is not an adapter.
|
||
//
|
||
|
||
do {
|
||
ArcDeviceName = BlGetNextToken(ArcDeviceName,
|
||
&ControllerName[0],
|
||
&ControllerNumber);
|
||
|
||
if (ArcDeviceName == NULL) {
|
||
return EINVAL;
|
||
}
|
||
|
||
MatchIndex = BlMatchToken(&ControllerName[0], &BlAdapterTypes[0]);
|
||
if (MatchIndex == AdapterMaximum) {
|
||
//
|
||
// If it is not an adapter, we must have reached the last
|
||
// adapter in the name. Fall through to the controller logic.
|
||
//
|
||
break;
|
||
} else {
|
||
//
|
||
// We have found another adapter, add it to
|
||
// the canonical adapter path
|
||
//
|
||
|
||
sprintf(AdapterPath+strlen(AdapterPath),
|
||
"%s(%d)",
|
||
ControllerName,
|
||
ControllerNumber);
|
||
|
||
}
|
||
|
||
} while ( TRUE );
|
||
|
||
MatchIndex = BlMatchToken(&ControllerName[0], &BlControllerTypes[0]);
|
||
switch (MatchIndex) {
|
||
|
||
//
|
||
// Cdrom controller.
|
||
//
|
||
// Get the peripheral name and make sure it is valid.
|
||
//
|
||
|
||
case ControllerCdrom:
|
||
ArcDeviceName = BlGetNextToken(ArcDeviceName,
|
||
&PeripheralName[0],
|
||
&PeripheralNumber);
|
||
|
||
if (ArcDeviceName == NULL) {
|
||
return EINVAL;
|
||
}
|
||
|
||
if (_stricmp(&PeripheralName[0], "fdisk") != 0) {
|
||
return EINVAL;
|
||
}
|
||
|
||
ArcDeviceName = BlGetNextToken(ArcDeviceName,
|
||
&TokenValue[0],
|
||
&MatchIndex);
|
||
|
||
if (ArcDeviceName != NULL) {
|
||
return EINVAL;
|
||
}
|
||
|
||
sprintf(ArcCanonicalName,
|
||
"%s%s(%d)%s(%d)",
|
||
&AdapterPath[0],
|
||
&ControllerName[0],
|
||
ControllerNumber,
|
||
&PeripheralName[0],
|
||
PeripheralNumber);
|
||
|
||
if (ARGUMENT_PRESENT(NtDevicePrefix)) {
|
||
strcpy(NtDevicePrefix, "\\Device\\CDRom");
|
||
}
|
||
break;
|
||
|
||
//
|
||
// Disk controller.
|
||
//
|
||
// Get the peripheral and make sure it is valid.
|
||
//
|
||
|
||
case ControllerDisk:
|
||
ArcDeviceName = BlGetNextToken(ArcDeviceName,
|
||
&PeripheralName[0],
|
||
&PeripheralNumber);
|
||
|
||
if (ArcDeviceName == NULL) {
|
||
return EINVAL;
|
||
}
|
||
|
||
MatchIndex = BlMatchToken(&PeripheralName[0], &BlPeripheralTypes[0]);
|
||
switch (MatchIndex) {
|
||
|
||
//
|
||
// Rigid Disk.
|
||
//
|
||
// If a partition is specified, then parse the partition number.
|
||
//
|
||
|
||
case PeripheralRigidDisk:
|
||
ArcDeviceName = BlGetNextToken(ArcDeviceName,
|
||
&PartitionName[0],
|
||
&PartitionNumber);
|
||
|
||
if (ArcDeviceName == NULL) {
|
||
strcpy(&PartitionName[0], "partition");
|
||
PartitionNumber = 1;
|
||
|
||
} else {
|
||
if (_stricmp(&PartitionName[0], "partition") != 0) {
|
||
return EINVAL;
|
||
}
|
||
|
||
ArcDeviceName = BlGetNextToken(ArcDeviceName,
|
||
&TokenValue[0],
|
||
&MatchIndex);
|
||
|
||
if (ArcDeviceName != NULL) {
|
||
return EINVAL;
|
||
}
|
||
}
|
||
|
||
sprintf(ArcCanonicalName,
|
||
"%s%s(%d)%s(%d)%s(%d)",
|
||
&AdapterPath[0],
|
||
&ControllerName[0],
|
||
ControllerNumber,
|
||
&PeripheralName[0],
|
||
PeripheralNumber,
|
||
&PartitionName[0],
|
||
PartitionNumber);
|
||
|
||
if (ARGUMENT_PRESENT(NtDevicePrefix)) {
|
||
strcpy(NtDevicePrefix, "\\Device\\Harddisk");
|
||
}
|
||
break;
|
||
|
||
//
|
||
// Floppy disk.
|
||
//
|
||
|
||
case PeripheralFloppyDisk:
|
||
#if defined(ARCI386)
|
||
ArcDeviceName = BlGetNextToken(ArcDeviceName,
|
||
&PartitionName[0],
|
||
&PartitionNumber);
|
||
|
||
if (ArcDeviceName == NULL) {
|
||
strcpy(&PartitionName[0], "partition");
|
||
PartitionNumber = 1;
|
||
|
||
} else {
|
||
if (_stricmp(&PartitionName[0], "partition") != 0) {
|
||
return EINVAL;
|
||
}
|
||
|
||
ArcDeviceName = BlGetNextToken(ArcDeviceName,
|
||
&TokenValue[0],
|
||
&MatchIndex);
|
||
|
||
if (ArcDeviceName != NULL) {
|
||
return EINVAL;
|
||
}
|
||
}
|
||
|
||
sprintf(ArcCanonicalName,
|
||
"%s%s(%d)%s(%d)%s(%d)",
|
||
&AdapterPath[0],
|
||
&ControllerName[0],
|
||
ControllerNumber,
|
||
&PeripheralName[0],
|
||
PeripheralNumber,
|
||
&PartitionName[0],
|
||
PartitionNumber);
|
||
#else
|
||
ArcDeviceName = BlGetNextToken(ArcDeviceName,
|
||
&TokenValue[0],
|
||
&MatchIndex);
|
||
|
||
if (ArcDeviceName != NULL) {
|
||
return EINVAL;
|
||
}
|
||
|
||
sprintf(ArcCanonicalName,
|
||
"%s%s(%d)%s(%d)",
|
||
&AdapterPath[0],
|
||
&ControllerName[0],
|
||
ControllerNumber,
|
||
&PeripheralName[0],
|
||
PeripheralNumber);
|
||
|
||
#endif // defined(NEC_98)
|
||
|
||
if (ARGUMENT_PRESENT(NtDevicePrefix)) {
|
||
strcpy(NtDevicePrefix, "\\Device\\Floppy");
|
||
}
|
||
break;
|
||
|
||
#if defined(ELTORITO)
|
||
//
|
||
// El Torito CD-ROM.
|
||
//
|
||
|
||
case PeripheralElTorito:
|
||
ArcDeviceName = BlGetNextToken(ArcDeviceName,
|
||
&TokenValue[0],
|
||
&MatchIndex);
|
||
|
||
if (ArcDeviceName != NULL) {
|
||
return EINVAL;
|
||
}
|
||
|
||
sprintf(ArcCanonicalName,
|
||
"%s%s(%d)%s(%d)",
|
||
&AdapterPath[0],
|
||
&ControllerName[0],
|
||
ControllerNumber,
|
||
&PeripheralName[0],
|
||
PeripheralNumber);
|
||
|
||
if (ARGUMENT_PRESENT(NtDevicePrefix)) {
|
||
strcpy(NtDevicePrefix, "\\Device\\CDRom");
|
||
}
|
||
break;
|
||
#endif
|
||
|
||
//
|
||
// Invalid peripheral.
|
||
//
|
||
|
||
default:
|
||
return EINVAL;
|
||
}
|
||
|
||
break;
|
||
|
||
//
|
||
// Invalid controller.
|
||
//
|
||
|
||
default:
|
||
return EINVAL;
|
||
}
|
||
|
||
return ESUCCESS;
|
||
}
|
||
|
||
PCHAR
|
||
BlGetNextToken (
|
||
IN PCHAR TokenString,
|
||
OUT PCHAR OutputToken,
|
||
OUT PULONG UnitNumber
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine scans the specified token string for the next token and
|
||
unit number. The token format is:
|
||
|
||
name[(unit)]
|
||
|
||
Arguments:
|
||
|
||
TokenString - Supplies a pointer to a zero terminated token string.
|
||
|
||
OutputToken - Supplies a pointer to a variable that receives the next
|
||
token.
|
||
|
||
UnitNumber - Supplies a pointer to a variable that receives the unit
|
||
number.
|
||
|
||
Return Value:
|
||
|
||
If another token exists in the token string, then a pointer to the
|
||
start of the next token is returned. Otherwise, a value of NULL is
|
||
returned.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
//
|
||
// If there are more characters in the token string, then parse the
|
||
// next token. Otherwise, return a value of NULL.
|
||
//
|
||
|
||
if (*TokenString == '\0') {
|
||
return NULL;
|
||
|
||
} else {
|
||
while ((*TokenString != '\0') && (*TokenString != '(')) {
|
||
*OutputToken++ = *TokenString++;
|
||
}
|
||
|
||
*OutputToken = '\0';
|
||
|
||
//
|
||
// If a unit number is specified, then convert it to binary.
|
||
// Otherwise, default the unit number to zero.
|
||
//
|
||
|
||
*UnitNumber = 0;
|
||
if (*TokenString == '(') {
|
||
TokenString += 1;
|
||
while ((*TokenString != '\0') && (*TokenString != ')')) {
|
||
*UnitNumber = (*UnitNumber * 10) + (*TokenString++ - '0');
|
||
}
|
||
|
||
if (*TokenString == ')') {
|
||
TokenString += 1;
|
||
}
|
||
}
|
||
}
|
||
|
||
return TokenString;
|
||
}
|
||
|
||
ULONG
|
||
BlMatchToken (
|
||
IN PCHAR TokenValue,
|
||
IN CHAR * FIRMWARE_PTR TokenArray[]
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine attempts to match a token with an array of possible
|
||
values.
|
||
|
||
Arguments:
|
||
|
||
TokenValue - Supplies a pointer to a zero terminated token value.
|
||
|
||
TokenArray - Supplies a pointer to a vector of pointers to null terminated
|
||
match strings.
|
||
|
||
Return Value:
|
||
|
||
If a token match is located, then the index of the matching value is
|
||
returned as the function value. Otherwise, an index one greater than
|
||
the size of the match array is returned.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
ULONG Index;
|
||
PCHAR MatchString;
|
||
PCHAR TokenString;
|
||
|
||
//
|
||
// Scan the match array until either a match is found or all of
|
||
// the match strings have been scanned.
|
||
//
|
||
|
||
Index = 0;
|
||
while (TokenArray[Index] != NULL) {
|
||
MatchString = TokenArray[Index];
|
||
TokenString = TokenValue;
|
||
while ((*MatchString != '\0') && (*TokenString != '\0')) {
|
||
if (toupper(*MatchString) != toupper(*TokenString)) {
|
||
break;
|
||
}
|
||
|
||
MatchString += 1;
|
||
TokenString += 1;
|
||
}
|
||
|
||
if ((*MatchString == '\0') && (*TokenString == '\0')) {
|
||
break;
|
||
}
|
||
|
||
Index += 1;
|
||
}
|
||
|
||
return Index;
|
||
}
|