Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

555 lines
16 KiB

/*++
Copyright (c) 1995-2001 Microsoft Corporation
Module Name:
efidrvent.c
Abstract:
Contains the EFI driver entry abstraction implementation.
Author:
Mandar Gokhale ([email protected]) 14-June-2002
Revision History:
None.
--*/
#include <efidrvent.h>
#include <ntosp.h>
#include <efi.h>
#include <stdio.h>
static
NTSTATUS
EFIDEAddOrUpdateDriverEntry(
IN PDRIVER_ENTRY This,
IN BOOLEAN IsUpdate
)
/*++
Description:
Modify or update a driver entry.
Arguments:
This - Driver entry .
IsUpdate - whether this is a driver entry update or add.
Return Value:
NTSTATUS or add/modify driver operation.
--*/
{
//
// Add this as new boot entry
//
ULONG FullPathLength = 0;
ULONG DevicePathLength = 0;
ULONG SrcPathLength = 0;
ULONG FriendlyNameOffset = 0;
ULONG FriendlyNameLength = 0;
ULONG FilePathLength = 0;
ULONG EntryLength = 0;
ULONG DriverEntryLength = 0;
PEFI_DRIVER_ENTRY DriverEntry = NULL;
PFILE_PATH FilePath;
NTSTATUS Status;
DevicePathLength = (wcslen((PCWSTR)This->NtDevicePath)+ 1) * sizeof(WCHAR);
SrcPathLength = (wcslen((PCWSTR)This->DirPath) + 1) * sizeof(WCHAR);
FullPathLength = DevicePathLength + SrcPathLength;
FriendlyNameOffset = ALIGN_UP(sizeof(EFI_DRIVER_ENTRY), WCHAR);
FriendlyNameLength = (wcslen(This->FriendlyName) + 1) * sizeof(WCHAR);
FilePathLength = FIELD_OFFSET(FILE_PATH, FilePath) + FullPathLength;
EntryLength = FriendlyNameOffset + ALIGN_UP(FriendlyNameLength, ULONG) + FilePathLength;
DriverEntry = SBE_MALLOC(EntryLength);
DriverEntry->Version = EFI_DRIVER_ENTRY_VERSION;
DriverEntry->Length = EntryLength;
DriverEntry->FriendlyNameOffset = FriendlyNameOffset;
DriverEntry->DriverFilePathOffset = FriendlyNameOffset +
ALIGN_UP(FriendlyNameLength, ULONG);
RtlCopyMemory((PCHAR) DriverEntry + DriverEntry->FriendlyNameOffset,
This->FriendlyName,
FriendlyNameLength);
FilePath = (PFILE_PATH) ((PCHAR) DriverEntry + DriverEntry->DriverFilePathOffset);
FilePath->Version = FILE_PATH_VERSION;
FilePath->Length = FilePathLength;
FilePath->Type = FILE_PATH_TYPE_NT;
RtlCopyMemory(FilePath->FilePath, This->NtDevicePath, DevicePathLength );
RtlCopyMemory(FilePath->FilePath + DevicePathLength, This->DirPath, SrcPathLength);
if (IsUpdate){
//
// Update the driver.
//
DriverEntry->Id = This->Id;
Status = NtModifyDriverEntry(DriverEntry);
} else {
//
// Add a new driver entry.
//
Status = NtAddDriverEntry(DriverEntry, &(This->Id));
}
//
// Free allocated memory.
//
if(DriverEntry){
SBE_FREE(DriverEntry);
}
return Status;
}
static
BOOLEAN
EFIDEFlushDriverEntry(
IN PDRIVER_ENTRY This // Points to the driver List.
)
{
BOOLEAN Result = FALSE;
if (This) {
NTSTATUS Status = STATUS_SUCCESS;
if (DRIVERENT_IS_DIRTY(This)) {
if (DRIVERENT_IS_DELETED(This)) {
//
// Delete this entry
//
Status = NtDeleteDriverEntry(This->Id);
} else if (DRIVERENT_IS_NEW(This)) {
//
// Add new Entry.
//
Status = EFIDEAddOrUpdateDriverEntry(This, FALSE);
} else {
//
// Just update this boot entry
//
Status = EFIDEAddOrUpdateDriverEntry(This, TRUE);
}
if (NT_SUCCESS(Status)) {
DRIVERENT_RESET_DIRTY(This);
Result = TRUE;
}
} else {
Result = TRUE; // nothing to flush
}
}
return Result;
}
__inline
BOOLEAN
EFIDEDriverMatch(
IN PDRIVER_ENTRY DriverEntry ,
IN PCWSTR SrcNtFullPath
)
{
BOOLEAN Result = FALSE;
if (!_wcsicmp(DriverEntry->FileName, (wcsrchr(SrcNtFullPath,L'\\')+1))){
Result = TRUE;
}
return(Result);
}
static
PDRIVER_ENTRY
EFIDESearchForDriverEntry(
IN POS_BOOT_OPTIONS This,
IN PCWSTR SrcNtFullPath
)
/*++
Description:
Searches our internal list of driver entries for a match.
It looks up the driver name (not including the path)
for a match. so a\b\c\driver.sys and e\f\driver.sys would be a match.
--*/
{
PDRIVER_ENTRY CurrentDriverEntry = NULL;
if (This && SrcNtFullPath){
CurrentDriverEntry = This->DriverEntries;
while (CurrentDriverEntry){
if (EFIDEDriverMatch(CurrentDriverEntry,
SrcNtFullPath)){
break;
}
CurrentDriverEntry = OSBOGetNextDriverEntry(This, CurrentDriverEntry);
}
}
return (CurrentDriverEntry);
}
PDRIVER_ENTRY
EFIDECreateNewDriverEntry(
IN POS_BOOT_OPTIONS This,
IN PCWSTR FriendlyName,
IN PCWSTR NtDevicePath,
IN PCWSTR DirPath
)
{
PDRIVER_ENTRY DriverEntry = NULL;
if (This && FriendlyName && DirPath && NtDevicePath){
PDRIVER_ENTRY CurrentDriverEntry = NULL;
DriverEntry = (PDRIVER_ENTRY)SBE_MALLOC(sizeof(DRIVER_ENTRY));
memset(DriverEntry, 0, sizeof(DRIVER_ENTRY));
EFIDEDriverEntryInit(DriverEntry);
DriverEntry->BootOptions = This;
//
// Set information for the driver entry.
//
OSDriverSetFileName(DriverEntry, DirPath);
OSDriverSetNtPath(DriverEntry, NtDevicePath);
OSDriverSetDirPath(DriverEntry, DirPath);
OSDriverSetFriendlyName(DriverEntry, FriendlyName);
//
// Mark the driver entry new and dirty.
//
DRIVERENT_SET_NEW(DriverEntry);
DRIVERENT_SET_DIRTY(DriverEntry);
}
return (DriverEntry);
}
PDRIVER_ENTRY
EFIOSBOInsertDriverListNewEntry(
IN POS_BOOT_OPTIONS This,
IN PDRIVER_ENTRY DriverEntry
)
{
if (This && DriverEntry){
PDRIVER_ENTRY CurrentDriverEntry = NULL;
//
// Insert into the list.
//
if (NULL == This->DriverEntries){
//
// No driver entries, this is the first one.
//
This->DriverEntries = DriverEntry;
}else{
//
// Insert in the existing list.
//
DriverEntry->NextEntry = This->DriverEntries;
This->DriverEntries = DriverEntry;
}
}
return (DriverEntry);
}
PDRIVER_ENTRY
EFIDEAddNewDriverEntry(
IN POS_BOOT_OPTIONS This,
IN PCWSTR FriendlyName,
IN PCWSTR NtDevicePath,
IN PCWSTR SrcNtFullPath
)
/*++
Description:
Used to add a new driver entry in NVRAM.
--*/
{
PEFI_DRIVER_ENTRY_LIST DriverList = NULL; // list of driver entries
PDRIVER_ENTRY DriverEntry = NULL;
if (This && FriendlyName && SrcNtFullPath && NtDevicePath){
DriverEntry = EFIDECreateNewDriverEntry(This,
FriendlyName,
NtDevicePath,
SrcNtFullPath);
//
// Mark it as new
//
DRIVERENT_IS_NEW(DriverEntry);
//
// flush the entry,
// see status, if successful put it in the list (only if new)
// otherwise free it
//
if (!OSDriverEntryFlush(DriverEntry)){
SBE_FREE(DriverEntry);
DriverEntry = NULL;
} else {
ULONG OrderCount;
PULONG NewOrder;
//
// If the driver was newly added one then insert it in the driver list.
//
if (DRIVERENT_IS_NEW(DriverEntry)){
EFIOSBOInsertDriverListNewEntry(This,
DriverEntry);
//
// Increment the count of the number of driver entries in the list.
//
This->DriverEntryCount++;
//
// Put the new entry at the end of the boot order
//
OrderCount = OSBOGetOrderedDriverEntryCount(This);
NewOrder = (PULONG)SBE_MALLOC((OrderCount + 1) * sizeof(ULONG));
if (NewOrder) {
memset(NewOrder, 0, sizeof(ULONG) * (OrderCount + 1));
//
// copy over the old ordered list
//
memcpy(NewOrder, This->DriverEntryOrder, sizeof(ULONG) * OrderCount);
NewOrder[OrderCount] = OSDriverGetId((PDRIVER_ENTRY)DriverEntry);
SBE_FREE(This->DriverEntryOrder);
This->DriverEntryOrder = NewOrder;
This->DriverEntryOrderCount = OrderCount + 1;
} else {
//
// Remove the driver entry out of the link list.
// Just freeing it will cause memory leaks.
// TBD: decide if we want to delete this driver entry too
//
This->DriverEntries = DriverEntry->NextEntry;
SBE_FREE(DriverEntry);
DriverEntry = NULL;
}
}
}
}
return DriverEntry;
}
__inline
ULONG
EFIDESetDriverId(
IN PDRIVER_ENTRY This,
IN ULONG DriverId
)
{
if (This){
This->Id = DriverId;
}
return (DriverId);
}
PDRIVER_ENTRY
EFIDECreateDriverEntry(PEFI_DRIVER_ENTRY_LIST Entry,
POS_BOOT_OPTIONS This )
/*++
Description:
Used to interpret a driver entry returned by NtEnumerateDriverEntries(..)
into our format.
Arguments:
Entry - EFI format driver entry returned to us by NT.
This - container for the driver entry list that we generate.
Return:
PDRIVER_ENTRY ( driver entry in our format).
--*/
{
PDRIVER_ENTRY ResultDriverEntry = NULL;
if (Entry && This){
PFILE_PATH FilePath = (PFILE_PATH) ((PCHAR) &Entry->DriverEntry +
Entry->DriverEntry.DriverFilePathOffset);
PWCHAR FriendlyName = (PWCHAR)((PCHAR)&Entry->DriverEntry +
Entry->DriverEntry.FriendlyNameOffset);
ULONG NtDevicePathLength = 0;
PDRIVER_ENTRY DriverEntry = NULL;
PFILE_PATH DriverOptionPath = NULL;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
if(FilePath->Type != FILE_PATH_TYPE_NT) {
PVOID Buffer;
ULONG PathLength = 0;
Status = NtTranslateFilePath(FilePath, FILE_PATH_TYPE_NT, NULL, &PathLength);
if(NT_SUCCESS(Status)) {
Status = STATUS_UNSUCCESSFUL;
}
if(STATUS_BUFFER_TOO_SMALL == Status) {
ASSERT(PathLength != 0);
DriverOptionPath = (PFILE_PATH)SBE_MALLOC(PathLength);
memset(DriverOptionPath, 0, sizeof(PathLength));
Status = NtTranslateFilePath(FilePath,
FILE_PATH_TYPE_NT,
DriverOptionPath,
&PathLength);
}
if(!NT_SUCCESS(Status)) {
if(STATUS_OBJECT_PATH_NOT_FOUND == Status || STATUS_OBJECT_NAME_NOT_FOUND == Status) {
//
// This entry is stale; remove it
//
NtDeleteDriverEntry(Entry->DriverEntry.Id);
}
//
// Free the DriverOptionPath memory
//
if(DriverOptionPath != NULL) {
SBE_FREE(DriverOptionPath);
DriverOptionPath = NULL;
}
}
}
if (DriverOptionPath){
ULONG FilePathLength = 0;
DriverEntry = (PDRIVER_ENTRY)SBE_MALLOC(sizeof(DRIVER_ENTRY));
memset(DriverEntry, 0, sizeof(DRIVER_ENTRY));
//
// Set pointer back to boot options (container).
//
DriverEntry->BootOptions = This;
EFIDEDriverEntryInit(DriverEntry);
//
// Set driver ID.
//
EFIDESetDriverId(DriverEntry, Entry->DriverEntry.Id);
//
// Set File Name.
//
NtDevicePathLength = wcslen((PCWSTR) DriverOptionPath->FilePath) + 1;
OSDriverSetFileName(DriverEntry,
(PCWSTR) DriverOptionPath->FilePath + NtDevicePathLength);
//
// Set NT path and Driver dir.
//
OSDriverSetNtPath(DriverEntry, (PCWSTR)DriverOptionPath->FilePath);
OSDriverSetDirPath(DriverEntry, (PCWSTR)(DriverOptionPath->FilePath) + NtDevicePathLength);
//
// Set Friendly Name.
//
OSDriverSetFriendlyName(DriverEntry, FriendlyName);
//
// Free the DriverOptionPath memory
//
if(DriverOptionPath != NULL) {
SBE_FREE(DriverOptionPath);
}
ResultDriverEntry = DriverEntry;
}
}
return ResultDriverEntry;
}
NTSTATUS
EFIDEInterpretDriverEntries(
IN POS_BOOT_OPTIONS This,
IN PEFI_DRIVER_ENTRY_LIST DriverList
)
/*++
Description:
Used to interpret the driver entries returned by NtEnumerateDriverEntries(..)
into our format.
Arguments:
This - container for the driver entry list that we generate.
DriverList - Driver list returned by NtEnumerateDriverEntries(..).
Return:
NTSTATUS code.
--*/
{
NTSTATUS Status = STATUS_UNSUCCESSFUL;
if (This && DriverList){
PEFI_DRIVER_ENTRY_LIST Entry;
PDRIVER_ENTRY DriverEntry = NULL;
BOOLEAN Continue = TRUE;
Status = STATUS_SUCCESS;
for(Entry = DriverList;
Continue;
Entry = (PEFI_DRIVER_ENTRY_LIST) ((PCHAR) Entry +
Entry->NextEntryOffset)) {
Continue = (Entry->NextEntryOffset != 0);
DriverEntry = EFIDECreateDriverEntry(Entry, This);
if (DriverEntry){
//
// Insert into the list of drivers in the OSBO structure.
//
if (NULL == This->DriverEntries){
This->DriverEntries = DriverEntry;
} else{
DriverEntry->NextEntry = This->DriverEntries;
This->DriverEntries = DriverEntry;
}
This->DriverEntryCount++;
}
}
}
return Status;
}
static
VOID
EFIDEDriverEntryInit(
IN PDRIVER_ENTRY This
)
{
This->Flush = EFIDEFlushDriverEntry;
}