mirror of
https://github.com/reactos/reactos.git
synced 2025-08-02 21:06:17 +00:00
[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:
parent
de0a6b1666
commit
68e9874f36
6 changed files with 966 additions and 23 deletions
|
@ -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;
|
||||
}
|
||||
|
||||
/*++
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue