[BOOTMGR]: Support for launching a recovery sequence.

[BOOTMGR]: Stub support for boot errors.
[BOOTMGR]: Stubplement support for device creation for boot applications (only for fully specified devices)
[BOOTMGR]: Implement support for execution transfer, including recovery mode/sequence.
[BOOTMGR]: Implement support for launching a boot entry.
[BOOTLIB]: Support for EFI Firmware device enumeration, driver attachment, and comparison.
[BOOTLIB]: Support for appending BOOLEAN or INTEGER BCD options.
Next step is the PE loader.

svn path=/trunk/; revision=70618
This commit is contained in:
Alex Ionescu 2016-01-19 18:21:54 +00:00
parent de0a6b1666
commit 68e9874f36
6 changed files with 966 additions and 23 deletions

View file

@ -1,7 +1,7 @@
/*
* COPYRIGHT: See COPYING.ARM in the top level directory
* PROJECT: ReactOS UEFI Boot Manager
* FILE: boot/environ/app/bootmgr/bootmgr.c
* FILE: boot/environ/app/bootmgr/bootmgr.cla
* PURPOSE: Boot Manager Entrypoint
* PROGRAMMER: Alex Ionescu (alex.ionescu@reactos.org)
*/
@ -2033,13 +2033,562 @@ NTSTATUS
BmpLaunchBootEntry (
_In_ PBL_LOADED_APPLICATION_ENTRY BootEntry,
_Out_ PULONG EntryIndex,
_In_ ULONG Unknown,
_In_ ULONG LaunchCode,
_In_ BOOLEAN LaunchWinRe
);
NTSTATUS
BmLaunchRecoverySequence (
_In_ PBL_LOADED_APPLICATION_ENTRY BootEntry,
_In_ ULONG LaunchCode
)
{
NTSTATUS Status;
PBL_LOADED_APPLICATION_ENTRY RecoveryEntry;
HANDLE BcdHandle;
PGUID RecoverySequence;
ULONG Count, i, RecoveryIndex, SequenceCount;
PBL_LOADED_APPLICATION_ENTRY* Sequence;
RecoveryIndex = 0;
Sequence = NULL;
RecoverySequence = NULL;
Count = 0;
BcdHandle = NULL;
Status = BmOpenDataStore(&BcdHandle);
if (NT_SUCCESS(Status))
{
Status = BlGetBootOptionGuidList(BootEntry->BcdData,
BcdLibraryObjectList_RecoverySequence,
&RecoverySequence,
&SequenceCount);
if (NT_SUCCESS(Status))
{
Status = BmGetBootSequence(BcdHandle,
RecoverySequence,
SequenceCount,
BL_APPLICATION_ENTRY_RECOVERY,
&Sequence,
&Count);
if (NT_SUCCESS(Status))
{
if (BcdHandle)
{
BmCloseDataStore(BcdHandle);
}
for (i = 0; i < Count; ++i)
{
if (LaunchCode == 2 || LaunchCode == 5)
{
BlRemoveBootOption(Sequence[i]->BcdData, BcdLibraryInteger_DisplayMessageOverride);
BlAppendBootOptionInteger(Sequence[i],
BcdLibraryInteger_DisplayMessageOverride,
4);
}
else if (LaunchCode == 3)
{
BlRemoveBootOption(Sequence[i]->BcdData, BcdLibraryInteger_DisplayMessageOverride);
BlAppendBootOptionInteger(Sequence[i],
BcdLibraryInteger_DisplayMessageOverride,
10);
}
Status = BmpLaunchBootEntry(Sequence[i], NULL, LaunchCode, FALSE);
if (!NT_SUCCESS(Status))
{
break;
}
}
}
if (Sequence)
{
for (RecoveryIndex = 0; RecoveryIndex < Count; RecoveryIndex++)
{
RecoveryEntry = Sequence[RecoveryIndex];
if (RecoveryEntry)
{
BlDestroyBootEntry(RecoveryEntry);
}
}
BlMmFreeHeap(Sequence);
}
}
if (RecoverySequence)
{
BlMmFreeHeap(RecoverySequence);
}
}
return Status;
}
ULONG
BmDisplayDumpError (
_In_ PBL_LOADED_APPLICATION_ENTRY BootEntry,
_In_ ULONG LaunchCode
)
{
ULONG BootError;
NTSTATUS Status;
BOOLEAN Restart, NoError;
BootError = 1;
Status = BlGetBootOptionBoolean(BlpApplicationEntry.BcdData,
BcdLibraryBoolean_RestartOnFailure,
&Restart);
if ((NT_SUCCESS(Status)) && (Restart))
{
return BootError;
}
Status = BlGetBootOptionBoolean(BlpApplicationEntry.BcdData,
BcdBootMgrBoolean_NoErrorDisplay,
&NoError);
if ((NT_SUCCESS(Status)) && (NoError))
{
return BootError;
}
if (BmpInternalBootError)
{
return (ULONG)BmpInternalBootError; // ???
}
EfiPrintf(L"Error menu not yet implemented\r\n");
return BootError;
}
NTSTATUS
BmpCreateDevices (
_In_ PBL_LOADED_APPLICATION_ENTRY BootEntry
)
{
ULONG NextOffset, DataOffset, ListOffset;
PBL_BCD_OPTION Option, ListOption;
BcdElementType ElementType;
PBCD_DEVICE_OPTION BcdDevice;
NextOffset = 0;
do
{
Option = (PBL_BCD_OPTION)((ULONG_PTR)BootEntry->BcdData + NextOffset);
NextOffset = Option->NextEntryOffset;
if (Option->Empty)
{
continue;
}
ElementType.PackedValue = Option->Type;
if (ElementType.Format != BCD_TYPE_DEVICE)
{
continue;
}
DataOffset = Option->DataOffset;
BcdDevice = (PBCD_DEVICE_OPTION)((ULONG_PTR)BootEntry->BcdData + DataOffset);
if (!(BcdDevice->DeviceDescriptor.Flags & 1))
{
continue;
}
ListOption = NULL;
ListOffset = Option->ListOffset;
if (Option->ListOffset)
{
ListOption = (PBL_BCD_OPTION)((ULONG_PTR)BootEntry->BcdData + ListOffset);
}
EfiPrintf(L"Unspecified devices not yet supported: %p\r\n", ListOption);
return STATUS_NOT_SUPPORTED;
} while (NextOffset != 0);
return STATUS_SUCCESS;
}
/* MOVE TO IMAGe.C */
NTSTATUS
BlImgLoadBootApplication (
_In_ PBL_LOADED_APPLICATION_ENTRY BootEntry,
_Out_ PHANDLE AppHandle
)
{
EfiPrintf(L"Loading application %p\r\n", BootEntry);
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
BlImgStartBootApplication (
_In_ HANDLE AppHandle,
_Inout_ PBL_RETURN_ARGUMENTS ReturnArguments
)
{
EfiPrintf(L"Starting application %p\r\n", AppHandle);
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
BlImgUnloadBootApplication (
_In_ HANDLE AppHandle
)
{
EfiPrintf(L"Unloading application %p\r\n", AppHandle);
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
BmpTransferExecution (
_In_ PBL_LOADED_APPLICATION_ENTRY BootEntry,
_Out_ PULONG LaunchCode,
_Out_ PBOOLEAN Recover
)
{
PWCHAR AppPath;
NTSTATUS Status;
PBL_DEVICE_DESCRIPTOR AppDevice;
BL_RETURN_ARGUMENTS ReturnArgs;
BOOLEAN AdvancedOptions;
HANDLE AppHandle;
Status = BlGetBootOptionString(BootEntry->BcdData,
BcdLibraryString_ApplicationPath,
&AppPath);
if (!NT_SUCCESS(Status))
{
AppPath = NULL;
}
if (BootEntry->Flags & BL_APPLICATION_ENTRY_STARTUP)
{
#if BL_NET_SUPPORT
Status = BlNetSoftReboot(BootEntry);
#else
EfiPrintf(L"Net boot not supported\r\n");
Status = STATUS_NOT_SUPPORTED;
#endif
goto Quickie;
}
do
{
Status = BlImgLoadBootApplication(BootEntry, &AppHandle);
if (Status == STATUS_NOT_FOUND)
{
Status = BlGetBootOptionDevice(BootEntry->BcdData,
BcdLibraryDevice_ApplicationDevice,
&AppDevice,
NULL);
if (NT_SUCCESS(Status))
{
Status = BlFwEnumerateDevice(AppDevice);
}
if (!NT_SUCCESS(Status))
{
BmFatalErrorEx(2, (ULONG_PTR)AppPath, Status, 0, 0);
goto Quickie;
}
Status = BlImgLoadBootApplication(BootEntry, &AppHandle);
}
if (Status == STATUS_CANCELLED)
{
if ((BmGetBootMenuPolicy(BootEntry) != MenuPolicyStandard) ||
!(MiscGetBootOption(BootEntry->BcdData,
BcdLibraryObjectList_RecoverySequence)))
{
goto Quickie;
}
*LaunchCode = 4;
*Recover = TRUE;
goto Quickie;
}
if (Status == 0xC0210000)
{
*LaunchCode = 4;
*Recover = TRUE;
goto Quickie;
}
if (!NT_SUCCESS(Status))
{
BmFatalErrorEx(2, (ULONG_PTR)AppPath, Status, 0, 0);
goto Quickie;
}
RtlZeroMemory(&ReturnArgs, sizeof(ReturnArgs));
//BmpLogApplicationLaunchEvent(&BootEntry->Guid, AppPath);
Status = BlImgStartBootApplication(AppHandle, &ReturnArgs);
#if BL_BITLOCKER_SUPPORT
BlFveSecureBootCheckpointAppReturn(BootEntry, &ReturnArgs);
#endif
//BlBsdLogEntry(1, 0x12, &BootEntry->Guid, 0x14);
BlImgUnloadBootApplication(AppHandle);
} while (Status != 0xC0000453);
*Recover = TRUE;
if (ReturnArgs.Flags & 1)
{
Status = BlGetBootOptionBoolean(BootEntry->BcdData,
BcdLibraryBoolean_DisplayAdvancedOptions,
&AdvancedOptions);
if ((NT_SUCCESS(Status)) && (AdvancedOptions))
{
*LaunchCode = 2;
}
else
{
*LaunchCode = 1;
}
}
else if (ReturnArgs.Flags & 4)
{
*LaunchCode = 1;
}
else if (ReturnArgs.Flags & 8)
{
*LaunchCode = 5;
}
else if (ReturnArgs.Flags & 0x10)
{
*LaunchCode = 6;
}
else if (ReturnArgs.Flags & 0x20)
{
*LaunchCode = 7;
}
else if (ReturnArgs.Flags & 0x40)
{
*Recover = FALSE;
BmFatalErrorEx(11, Status, 0, 0, 0);
}
Quickie:
if (AppPath)
{
BlMmFreeHeap(AppPath);
}
return Status;
}
NTSTATUS
BmpLaunchBootEntry (
_In_ PBL_LOADED_APPLICATION_ENTRY BootEntry,
_Out_ PULONG EntryIndex,
_In_ ULONG LaunchCode,
_In_ BOOLEAN LaunchWinRe
)
{
EfiPrintf(L"Boot launch not yet implemented\r\n");
EfiStall(1000000000);
return STATUS_NOT_IMPLEMENTED;
HANDLE BcdHandle;
NTSTATUS Status;
GUID ObjectId;
BOOLEAN DoRecovery, AutoRecovery, DoRestart, RestartOnFailure;
ULONG ErrorCode;
BOOLEAN AdvancedOneTime, EditOneTime, Recover;
if (BootEntry->Flags & BL_APPLICATION_ENTRY_WINLOAD)
{
if (MiscGetBootOption(BootEntry->BcdData, BcdOSLoaderBoolean_AdvancedOptionsOneTime))
{
BcdHandle = NULL;
Status = BmOpenDataStore(BcdHandle);
if (NT_SUCCESS(Status))
{
ObjectId = BootEntry->Guid;
BmPurgeOption(BcdHandle, &ObjectId, BcdOSLoaderBoolean_AdvancedOptionsOneTime);
BmCloseDataStore(BcdHandle);
}
}
if (MiscGetBootOption(BootEntry->BcdData, BcdOSLoaderBoolean_OptionsEditOneTime))
{
BcdHandle = NULL;
Status = BmOpenDataStore(BcdHandle);
if (NT_SUCCESS(Status))
{
ObjectId = BootEntry->Guid;
BmPurgeOption(BcdHandle, &ObjectId, BcdOSLoaderBoolean_OptionsEditOneTime);
BmCloseDataStore(BcdHandle);
}
}
}
TryAgain:
DoRecovery = FALSE;
Recover = FALSE;
BmpSelectedBootEntry = BootEntry;
Status = BmpCreateDevices(BootEntry);
if (!NT_SUCCESS(Status))
{
if (!LaunchWinRe)
{
return Status;
}
LaunchCode = 2;
goto Quickie;
}
if (BootEntry->Flags & BL_APPLICATION_ENTRY_WINLOAD)
{
Status = BlGetBootOptionBoolean(BootEntry->BcdData, BcdOSLoaderBoolean_AdvancedOptionsOneTime, &AdvancedOneTime);
if (NT_SUCCESS(Status))
{
if (AdvancedOneTime)
{
BlAppendBootOptionBoolean(BootEntry, BcdLibraryBoolean_DisplayAdvancedOptions);
}
else
{
BlRemoveBootOption(BootEntry->BcdData, BcdLibraryBoolean_DisplayAdvancedOptions);
}
BlRemoveBootOption(BootEntry->BcdData, BcdOSLoaderBoolean_AdvancedOptionsOneTime);
}
Status = BlGetBootOptionBoolean(BootEntry->BcdData, BcdOSLoaderBoolean_OptionsEditOneTime, &EditOneTime);
if (NT_SUCCESS(Status))
{
if (AdvancedOneTime)
{
BlAppendBootOptionBoolean(BootEntry, BcdLibraryBoolean_DisplayOptionsEdit);
}
else
{
BlRemoveBootOption(BootEntry->BcdData, BcdLibraryBoolean_DisplayOptionsEdit);
}
BlRemoveBootOption(BootEntry->BcdData, BcdOSLoaderBoolean_OptionsEditOneTime);
}
}
Status = BmpTransferExecution(BootEntry, &LaunchCode, &Recover);
if (!LaunchWinRe)
{
return Status;
}
DoRecovery = Recover;
if (((NT_SUCCESS(Status)) || (Status == STATUS_CANCELLED)) && !(Recover))
{
return Status;
}
if (!Recover)
{
LaunchCode = 2;
goto Quickie;
}
Quickie:
if (MiscGetBootOption(BootEntry->BcdData, BcdLibraryObjectList_RecoverySequence))
{
if ((LaunchCode == 3) || (LaunchCode == 5) || (LaunchCode == 6))
{
Status = BlGetBootOptionBoolean(BootEntry->BcdData, BcdLibraryBoolean_AutoRecoveryEnabled, &AutoRecovery);
if (NT_SUCCESS(Status))
{
DoRecovery = AutoRecovery;
}
}
}
else
{
DoRecovery = FALSE;
}
RestartOnFailure = FALSE;
BlGetBootOptionBoolean(BlpApplicationEntry.BcdData, BcdLibraryBoolean_RestartOnFailure, &RestartOnFailure);
DoRestart = RestartOnFailure ? FALSE : DoRecovery;
while (1)
{
if (DoRestart)
{
if (AutoRecovery)
{
//BlFveRegisterBootEntryForTrustedWimBoot(BootEntry, TRUE);
}
Status = BmLaunchRecoverySequence(BootEntry, LaunchCode);
if (AutoRecovery)
{
//BlFveRegisterBootEntryForTrustedWimBoot(BootEntry, FALSE);
AutoRecovery = FALSE;
}
if (NT_SUCCESS(Status))
{
return STATUS_SUCCESS;
}
BlRemoveBootOption(BootEntry->BcdData, BcdLibraryObjectList_RecoverySequence);
}
if (!BmpInternalBootError)
{
BmFatalErrorEx(4, Status, 0, 0, 0);
}
ErrorCode = BmDisplayDumpError(BootEntry, LaunchCode);
BmErrorPurge();
switch (ErrorCode)
{
case 6:
goto TryAgain;
case 5:
break;
case 4:
return STATUS_CANCELLED;
case 3:
Status = BmOpenDataStore(BcdHandle);
if (NT_SUCCESS(Status))
{
Status = BmProcessCustomAction(BcdHandle, NULL);
}
if (BcdHandle)
{
BmCloseDataStore(BcdHandle);
}
return Status;
case 7:
BlAppendBootOptionBoolean(BootEntry, BcdOSLoaderBoolean_AdvancedOptionsOneTime);
goto TryAgain;
case 8:
BlAppendBootOptionBoolean(BootEntry, BcdOSLoaderBoolean_OptionsEditOneTime);
goto TryAgain;
case 2:
DoRestart = TRUE;
LaunchCode = 1;
goto TryAgain;
default:
return STATUS_CANCELLED;
}
}
return STATUS_SUCCESS;
}
/*++

View file

@ -92,6 +92,8 @@ typedef enum BcdLibraryElementTypes
BcdLibraryInteger_FveBandId = 0x1500004C,
BcdLibraryBoolean_ConsoleExtendedInput = 0x16000050,
BcdLibraryInteger_GraphicsResolution = 0x15000052,
BcdLibraryInteger_DisplayMessage = 0x15000065, /* Undocumented */
BcdLibraryInteger_DisplayMessageOverride = 0x15000066, /* Undocumented */
BcdLibraryBoolean_RestartOnFailure = 0x16000053,
BcdLibraryBoolean_GraphicsForceHighestMode = 0x16000054,
BcdLibraryBoolean_IsolatedExecutionContext = 0x16000060,
@ -151,6 +153,7 @@ typedef enum BcdOSLoaderElementTypes
BcdOSLoaderInteger_DriverLoadFailurePolicy = 0x250000c1,
BcdOSLoaderInteger_BootMenuPolicy = 0x250000C2,
BcdOSLoaderBoolean_AdvancedOptionsOneTime = 0x260000C3,
BcdOSLoaderBoolean_OptionsEditOneTime = 0x260000C4, /* Undocumented */
BcdOSLoaderInteger_BootStatusPolicy = 0x250000E0,
BcdOSLoaderBoolean_DisableElamDrivers = 0x260000E1,
BcdOSLoaderInteger_HypervisorLaunchType = 0x250000F0,

View file

@ -77,6 +77,7 @@ DEFINE_GUID(BadMemoryGuid, 0x54B8275B, 0xD431, 0x473F, 0xAC, 0xFB, 0xE5, 0x36, 0
#define BL_APPLICATION_ENTRY_BOOTMGR 0x1000
#define BL_APPLICATION_ENTRY_DISPLAY_ORDER 0x800000
#define BL_APPLICATION_ENTRY_FIXED_SEQUENCE 0x20000000
#define BL_APPLICATION_ENTRY_RECOVERY 0x40000000
#define BL_CONTEXT_PAGING_ON 1
#define BL_CONTEXT_INTERRUPTS_ON 2
@ -110,6 +111,8 @@ DEFINE_GUID(BadMemoryGuid, 0x54B8275B, 0xD431, 0x473F, 0xAC, 0xFB, 0xE5, 0x36, 0
#define BL_FS_REGISTER_AT_HEAD_FLAG 1
#define BL_BLOCK_DEVICE_REMOVABLE_FLAG 0x01
#define BL_BLOCK_DEVICE_PRESENT_FLAG 0x02
#define BL_BLOCK_DEVICE_VIRTUAL_FLAG 0x04
#define BL_MEMORY_CLASS_SHIFT 28
@ -685,7 +688,9 @@ typedef struct _BL_RETURN_ARGUMENTS
{
ULONG Version;
NTSTATUS Status;
ULONG ReturnArgumentData[5];
ULONG Flags;
ULONGLONG DataSize;
ULONGLONG DataPage;
} BL_RETURN_ARGUMENTS, *PBL_RETURN_ARGUMENTS;
typedef struct _BL_MEMORY_DESCRIPTOR
@ -794,8 +799,10 @@ typedef struct _BL_LOCAL_DEVICE
LARGE_INTEGER ImageSize;
ULONG ImageOffset;
} RamDisk;
ULONG File; // unknown for now
};
} BL_LOCAL_DEVICE;
} BL_LOCAL_DEVICE, *PBL_LOCAL_DEVICE;
typedef struct _BL_DEVICE_DESCRIPTOR
{
@ -1316,6 +1323,11 @@ EfiPrintf (
...
);
NTSTATUS
BlFwEnumerateDevice (
_In_ PBL_DEVICE_DESCRIPTOR Device
);
NTSTATUS
EfiAllocatePages (
_In_ ULONG Type,
@ -1776,6 +1788,19 @@ BlCopyBootOptions (
_Out_ PBL_BCD_OPTION *CopiedOptions
);
NTSTATUS
BlAppendBootOptionBoolean (
_In_ PBL_LOADED_APPLICATION_ENTRY AppEntry,
_In_ ULONG OptionId
);
NTSTATUS
BlAppendBootOptionInteger (
_In_ PBL_LOADED_APPLICATION_ENTRY AppEntry,
_In_ ULONG OptionId,
_In_ ULONGLONG Value
);
NTSTATUS
BlAppendBootOptionString (
_In_ PBL_LOADED_APPLICATION_ENTRY AppEntry,
@ -2142,6 +2167,14 @@ BlFileOpen (
_Out_ PULONG FileId
);
/* BLOCK I/O ROUTINES *******************************************************/
NTSTATUS
BlockIoEfiCompareDevice (
_In_ PBL_DEVICE_DESCRIPTOR Device,
_In_ EFI_HANDLE Handle
);
/* INPUT CONSOLE ROUTINES ****************************************************/
VOID

View file

@ -1049,6 +1049,42 @@ EfiResetSystem (
EfiRT->ResetSystem(ResetType, EFI_SUCCESS, 0, NULL);
}
NTSTATUS
EfiConnectController (
_In_ EFI_HANDLE ControllerHandle
)
{
BL_ARCH_MODE OldMode;
EFI_STATUS EfiStatus;
/* Is this EFI 1.02? */
if (EfiST->Hdr.Revision == EFI_1_02_SYSTEM_TABLE_REVISION)
{
/* This function didn't exist back then */
return STATUS_NOT_SUPPORTED;
}
/* Are we in protected mode? */
OldMode = CurrentExecutionContext->Mode;
if (OldMode != BlRealMode)
{
/* FIXME: Not yet implemented */
return STATUS_NOT_IMPLEMENTED;
}
/* Make the EFI call */
EfiStatus = EfiBS->ConnectController(ControllerHandle, NULL, NULL, TRUE);
/* Switch back to protected mode if we came from there */
if (OldMode != BlRealMode)
{
BlpArchSwitchContext(OldMode);
}
/* Convert the error to an NTSTATUS */
return EfiGetNtStatusCode(EfiStatus);
}
NTSTATUS
EfiAllocatePages (
_In_ ULONG Type,
@ -1748,6 +1784,91 @@ BlpFwInitialize (
return Status;
}
NTSTATUS
BlFwEnumerateDevice (
_In_ PBL_DEVICE_DESCRIPTOR Device
)
{
NTSTATUS Status;
ULONG PathProtocols, BlockProtocols;
EFI_HANDLE* PathArray;
EFI_HANDLE* BlockArray;
/* Initialize locals */
BlockArray = NULL;
PathArray = NULL;
PathProtocols = 0;
BlockProtocols = 0;
/* Enumeration only makes sense on disks or partitions */
if ((Device->DeviceType != DiskDevice) &&
(Device->DeviceType != LegacyPartitionDevice) &&
(Device->DeviceType != PartitionDevice))
{
return STATUS_NOT_SUPPORTED;
}
/* Enumerate the list of device paths */
Status = EfiLocateHandleBuffer(ByProtocol,
&EfiDevicePathProtocol,
&PathProtocols,
&PathArray);
if (NT_SUCCESS(Status))
{
/* Loop through each one */
Status = STATUS_NOT_FOUND;
while (PathProtocols)
{
/* Attempt to connect the driver for this device epath */
Status = EfiConnectController(PathArray[--PathProtocols]);
if (NT_SUCCESS(Status))
{
/* Now enumerate any block I/O devices the driver added */
Status = EfiLocateHandleBuffer(ByProtocol,
&EfiBlockIoProtocol,
&BlockProtocols,
&BlockArray);
if (!NT_SUCCESS(Status))
{
break;
}
/* Loop through each one */
while (BlockProtocols)
{
/* Check if one of the new devices is the one we want */
Status = BlockIoEfiCompareDevice(Device,
BlockArray[--BlockProtocols]);
if (NT_SUCCESS(Status))
{
/* Yep, all done */
goto Quickie;
}
}
/* Move on to the next device path */
BlMmFreeHeap(BlockArray);
BlockArray = NULL;
}
}
}
Quickie:
/* We're done -- free the array of device path protocols, if any */
if (PathArray)
{
BlMmFreeHeap(PathArray);
}
/* We're done -- free the array of block I/O protocols, if any */
if (BlockArray)
{
BlMmFreeHeap(BlockArray);
}
/* Return if we found the device or not */
return Status;
}
/*++
* @name EfiGetEfiStatusCode

View file

@ -371,7 +371,7 @@ BlockIopReadPhysicalDevice (
)
{
PBL_BLOCK_DEVICE BlockDevice;
PVOID ReadBuffer; // edi@1
PVOID ReadBuffer;
ULONGLONG OffsetEnd, AlignedOffsetEnd, Offset;
NTSTATUS Status;
@ -532,24 +532,32 @@ BlockIoRead (
PBL_BLOCK_DEVICE BlockDevice;
NTSTATUS Status;
/* Get the device-specific data, which is our block device descriptor */
BlockDevice = DeviceEntry->DeviceSpecificData;
/* Make sure that the buffer and size is valid */
Status = BlockIopBlockInformationCheck(BlockDevice, &Size, BytesRead, &Size);
if (NT_SUCCESS(Status))
{
if (BlockDevice->DeviceFlags & 4)
/* Check if this is a virtual device or a physical device */
if (BlockDevice->DeviceFlags & BL_BLOCK_DEVICE_VIRTUAL_FLAG)
{
/* Do a virtual read or write */
Status = BlockIopReadWriteVirtualDevice(DeviceEntry, Buffer, Size, 0, BytesRead);
}
else
{
/* Do a physical read or write */
Status = BlockIopReadPhysicalDevice(DeviceEntry, Buffer, Size, BytesRead);
}
}
else if (BytesRead)
{
/* We failed, if the caller wanted bytes read, return 0 */
*BytesRead = 0;
}
/* Return back to the caller */
return Status;
}
@ -564,16 +572,25 @@ BlockIoSetInformation (
BlockDevice = DeviceEntry->DeviceSpecificData;
Offset = DeviceInformation->BlockDeviceInfo.Block * BlockDevice->BlockSize + DeviceInformation->BlockDeviceInfo.Offset;
/* Take the current block number and block-offset and conver to full offset */
Offset = DeviceInformation->BlockDeviceInfo.Block * BlockDevice->BlockSize +
DeviceInformation->BlockDeviceInfo.Offset;
/* Make sure that the full offset is still within the bounds of the device */
if (Offset > ((BlockDevice->LastBlock + 1) * BlockDevice->BlockSize - 1))
{
EfiPrintf(L"Invalid offset\r\n");
EfiPrintf(L"Offset out of bounds\r\n");
return STATUS_INVALID_PARAMETER;
}
/* Convery the full raw offset into a block number and block-offset */
BlockDevice->Block = Offset / BlockDevice->BlockSize;
BlockDevice->Offset = Offset % BlockDevice->BlockSize;
/* Return the unknown */
BlockDevice->Unknown = DeviceInformation->BlockDeviceInfo.Unknown;
/* All done */
return STATUS_SUCCESS;
}
@ -583,13 +600,12 @@ BlockIoGetInformation (
_Out_ PBL_DEVICE_INFORMATION DeviceInformation
)
{
PBL_BLOCK_DEVICE BlockDevice;
BlockDevice = DeviceEntry->DeviceSpecificData;
/* Copy the device speciifc data into the block device information */
RtlCopyMemory(&DeviceInformation->BlockDeviceInfo,
BlockDevice,
sizeof(DeviceInformation->BlockDeviceInfo));
DeviceEntry->DeviceSpecificData,
sizeof(DeviceInformation->BlockDeviceInfo));
/* Hardcode the device type */
DeviceInformation->DeviceType = DiskDevice;
return STATUS_SUCCESS;
}
@ -732,22 +748,28 @@ BlDeviceReadAtOffset (
)
{
NTSTATUS Status;
BL_DEVICE_INFORMATION DeviceInformation;
BL_DEVICE_INFORMATION DeviceInfo;
Status = BlDeviceGetInformation(DeviceId, &DeviceInformation);
/* Get the current block and offset */
Status = BlDeviceGetInformation(DeviceId, &DeviceInfo);
if (!NT_SUCCESS(Status))
{
return Status;
}
DeviceInformation.BlockDeviceInfo.Block = Offset / DeviceInformation.BlockDeviceInfo.BlockSize;
DeviceInformation.BlockDeviceInfo.Offset = Offset % DeviceInformation.BlockDeviceInfo.BlockSize;
Status = BlDeviceSetInformation(DeviceId, &DeviceInformation);
/* Get the block and block-offset based on the new raw offset */
DeviceInfo.BlockDeviceInfo.Block = Offset / DeviceInfo.BlockDeviceInfo.BlockSize;
DeviceInfo.BlockDeviceInfo.Offset = Offset % DeviceInfo.BlockDeviceInfo.BlockSize;
/* Update the block and offset */
Status = BlDeviceSetInformation(DeviceId, &DeviceInfo);
if (NT_SUCCESS(Status))
{
/* Now issue a read, with this block and offset configured */
Status = BlDeviceRead(DeviceId, Buffer, Size, BytesRead);
}
/* All good, return the caller */
return Status;
}
@ -828,7 +850,7 @@ BlockIoEfiGetBlockIoInformation (
}
if (Media->MediaPresent)
{
BlockDevice->DeviceFlags |= 2;
BlockDevice->DeviceFlags |= BL_BLOCK_DEVICE_PRESENT_FLAG;
}
/* No clue */
@ -1211,6 +1233,158 @@ BlockIoEfiCreateDeviceEntry (
return Status;
}
NTSTATUS
BlockIoEfiCompareDevice (
_In_ PBL_DEVICE_DESCRIPTOR Device,
_In_ EFI_HANDLE Handle
)
{
PBL_LOCAL_DEVICE LocalDeviceInfo, EfiLocalDeviceInfo;
PBL_DEVICE_ENTRY DeviceEntry;
PBL_DEVICE_DESCRIPTOR EfiDevice;
NTSTATUS Status;
DeviceEntry = NULL;
/* Check if no device was given */
if (!Device)
{
/* Fail the comparison */
Status = STATUS_INVALID_PARAMETER;
goto Quickie;
}
/* Check if this is a local disk device */
if (Device->DeviceType != DiskDevice)
{
/* Nope -- is it a partition device? */
if ((Device->DeviceType != LegacyPartitionDevice) &&
(Device->DeviceType != PartitionDevice))
{
/* Nope, so we can't compare */
Status = STATUS_INVALID_PARAMETER;
goto Quickie;
}
/* If so, return the device information for the parent disk */
LocalDeviceInfo = &Device->Partition.Disk;
}
else
{
/* Just return the disk information itself */
LocalDeviceInfo = &Device->Local;
}
/* Create an EFI device entry for the EFI device handle */
Status = BlockIoEfiCreateDeviceEntry(&DeviceEntry, Handle);
if (!NT_SUCCESS(Status))
{
goto Quickie;
}
/* Read the descriptor and assume failure for now */
EfiDevice = DeviceEntry->DeviceDescriptor;
Status = STATUS_UNSUCCESSFUL;
/* Check if the EFI device is a disk */
if (EfiDevice->DeviceType != DiskDevice)
{
/* Nope, is it a partition? */
if ((EfiDevice->DeviceType != LegacyPartitionDevice) &&
(EfiDevice->DeviceType != PartitionDevice))
{
/* Neither, invalid handle so bail out */
Status = STATUS_INVALID_PARAMETER;
goto Quickie;
}
/* Yes, so get the information of the parent disk */
EfiLocalDeviceInfo = &EfiDevice->Partition.Disk;
}
else
{
/* It's a disk, so get the disk information itself */
EfiLocalDeviceInfo = &EfiDevice->Local;
}
/* Are the two devices the same type? */
if (EfiLocalDeviceInfo->Type != LocalDeviceInfo->Type)
{
/* Nope, that was easy */
goto Quickie;
}
/* Yes, what kind of device is the EFI side? */
switch (EfiLocalDeviceInfo->Type)
{
case LocalDevice:
/* Local hard drive, compare the signature */
if (RtlCompareMemory(&EfiLocalDeviceInfo->HardDisk,
&LocalDeviceInfo->HardDisk,
sizeof(LocalDeviceInfo->HardDisk)) ==
sizeof(LocalDeviceInfo->HardDisk))
{
Status = STATUS_SUCCESS;
}
break;
case FloppyDevice:
case CdRomDevice:
/* Removable floppy or CD, compare the disk number */
if (RtlCompareMemory(&EfiLocalDeviceInfo->FloppyDisk,
&LocalDeviceInfo->FloppyDisk,
sizeof(LocalDeviceInfo->FloppyDisk)) ==
sizeof(LocalDeviceInfo->FloppyDisk))
{
Status = STATUS_SUCCESS;
}
break;
case RamDiskDevice:
/* RAM disk, compare the size and base information */
if (RtlCompareMemory(&EfiLocalDeviceInfo->RamDisk,
&LocalDeviceInfo->RamDisk,
sizeof(LocalDeviceInfo->RamDisk)) ==
sizeof(LocalDeviceInfo->RamDisk))
{
Status = STATUS_SUCCESS;
}
break;
case FileDevice:
/* File, compare the file identifier */
if (RtlCompareMemory(&EfiLocalDeviceInfo->File,
&LocalDeviceInfo->File,
sizeof(LocalDeviceInfo->File)) ==
sizeof(LocalDeviceInfo->File))
{
Status = STATUS_SUCCESS;
}
break;
/* Something else we don't support */
default:
break;
}
Quickie:
/* All done, did we have an EFI device entry? */
if (DeviceEntry)
{
/* Free it, since we only needed it locally for comparison */
BlMmFreeHeap(DeviceEntry->DeviceDescriptor);
BlockIopFreeAllocations(DeviceEntry->DeviceSpecificData);
BlMmFreeHeap(DeviceEntry);
}
/* Return back to the caller */
return Status;
}
NTSTATUS
BlockIoFirmwareOpen (
_In_ PBL_DEVICE_DESCRIPTOR Device,

View file

@ -621,6 +621,69 @@ BlCopyBootOptions (
return Status;
}
NTSTATUS
BlAppendBootOptionBoolean (
_In_ PBL_LOADED_APPLICATION_ENTRY AppEntry,
_In_ ULONG OptionId
)
{
NTSTATUS Status;
PBL_BCD_OPTION Option;
/* Allocate space for the entry -- remember BOOLEANs are USHORTs in BCD */
Option = BlMmAllocateHeap(sizeof(*Option) + sizeof(USHORT));
if (!Option)
{
return STATUS_NO_MEMORY;
}
/* Initialize it and set the boolean to TRUE */
RtlZeroMemory(Option, sizeof(*Option) + sizeof(USHORT));
Option->DataSize = sizeof(USHORT);
Option->Type = OptionId;
Option->DataOffset = sizeof(*Option);
*(PBOOLEAN)(Option + 1) = TRUE;
/* Append it */
Status = BlAppendBootOptions(AppEntry, Option);
/* We're all done, free our initial option */
BlMmFreeHeap(Option);
return Status;
}
NTSTATUS
BlAppendBootOptionInteger (
_In_ PBL_LOADED_APPLICATION_ENTRY AppEntry,
_In_ ULONG OptionId,
_In_ ULONGLONG Value
)
{
NTSTATUS Status;
PBL_BCD_OPTION Option;
/* Allocate space for the entry */
Option = BlMmAllocateHeap(sizeof(*Option) + sizeof(Value));
if (!Option)
{
return STATUS_NO_MEMORY;
}
/* Initialize it and set the integer to the given value */
RtlZeroMemory(Option, sizeof(*Option) + sizeof(Value));
Option->DataSize = sizeof(Value);
Option->Type = OptionId;
Option->DataOffset = sizeof(*Option);
*(PULONGLONG)(Option + 1) = Value;
/* Append it */
Status = BlAppendBootOptions(AppEntry, Option);
/* We're all done, free our initial option */
BlMmFreeHeap(Option);
return Status;
}
NTSTATUS
BlAppendBootOptionString (
_In_ PBL_LOADED_APPLICATION_ENTRY AppEntry,