Author: ion
Date: Sat Jan 9 05:39:18 2016
New Revision: 70556
URL:
http://svn.reactos.org/svn/reactos?rev=70556&view=rev
Log:
[BOOTMGFW]: Implement the final boot selection & launch loop.
[BOOTMLIB]: Implement a few more BCD option functions.
Minus a PE loader (BmpLaunchBootEntry) and some more BCD parsing (BmpGetSelectedBootEntry)
with some glue in between, the UEFI Boot Manager is nearly done. Once it is, it will be
time to implement the actual loader -- Winload.efi. The good news is that we'll have
all of bootlib already good to go (with all its hacks). The bad news is that Winload will
turn on paging, so all those unimplemented paths and UEFI mode switches will have to be
made to work.
Modified:
trunk/reactos/boot/environ/app/bootmgr/bootmgr.c
trunk/reactos/boot/environ/include/bl.h
trunk/reactos/boot/environ/lib/bootlib.c
trunk/reactos/boot/environ/lib/misc/bcdopt.c
Modified: trunk/reactos/boot/environ/app/bootmgr/bootmgr.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/boot/environ/app/bootmgr/b…
==============================================================================
--- trunk/reactos/boot/environ/app/bootmgr/bootmgr.c [iso-8859-1] (original)
+++ trunk/reactos/boot/environ/app/bootmgr/bootmgr.c [iso-8859-1] Sat Jan 9 05:39:18
2016
@@ -1163,6 +1163,66 @@
return STATUS_NOT_IMPLEMENTED;
}
+NTSTATUS
+BmpProcessBadMemory (
+ VOID
+ )
+{
+ EfiPrintf(L"Bad page list persistence \r\n");
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+BmPurgeOption (
+ _In_ HANDLE BcdHandle,
+ _In_ PGUID ObjectId,
+ _In_ ULONG Type
+ )
+{
+ EfiPrintf(L"Key BCD delete not yet implemented\r\n");
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+BmGetBootSequence (
+ _In_ HANDLE BcdHandle,
+ _In_ PGUID SequenceList,
+ _In_ ULONG SequenceListCount,
+ _In_ ULONG Flags,
+ _Out_ PBL_LOADED_APPLICATION_ENTRY** BootSequence,
+ _Out_ PULONG SequenceCount
+ )
+{
+ EfiPrintf(L"Fixed sequences not yet supported\r\n");
+ *SequenceCount = 0;
+ *BootSequence = NULL;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+BmpGetSelectedBootEntry (
+ _In_ HANDLE BcdHandle,
+ _Out_ PBL_LOADED_APPLICATION_ENTRY *SelectedBootEntry,
+ _Out_ PULONG EntryIndex,
+ _Out_ PBOOLEAN ExitBootManager
+ )
+{
+ EfiPrintf(L"Boot selection not yet implemented\r\n");
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+BmpLaunchBootEntry (
+ _In_ PBL_LOADED_APPLICATION_ENTRY BootEntry,
+ _Out_ PULONG EntryIndex,
+ _In_ ULONG Unknown,
+ _In_ BOOLEAN LaunchWinRe
+ )
+{
+ EfiPrintf(L"Boot launch not yet implemented\r\n");
+ return STATUS_NOT_IMPLEMENTED;
+}
+
/*++
* @name BmMain
*
@@ -1189,12 +1249,18 @@
PBL_BCD_OPTION EarlyOptions;
PWCHAR Stylesheet;
BOOLEAN XmlLoaded, DisableIntegrity, TestSigning, PersistBootSequence;
- BOOLEAN RebootOnError, CustomActions, ContinueLoop;
- ULONG SequenceId, SequenceCount;
- PGUID BootSequences;
- //PBL_LOADED_APPLICATION_ENTRY* BootEntries;
- //PBL_LOADED_APPLICATION_ENTRY BootEntry;
-
+ BOOLEAN RebootOnError, CustomActions;
+ ULONG SequenceId;
+ PBL_LOADED_APPLICATION_ENTRY BootEntry;
+ PGUID SequenceList;
+ ULONG SequenceListCount;
+ PBL_LOADED_APPLICATION_ENTRY* BootSequence;
+ ULONG BootIndex;
+ BOOLEAN ExitBootManager;
+ BOOLEAN BootFailed;
+ BOOLEAN BootOk;
+ ULONG SequenceCount;
+ BOOLEAN GetEntry;
EfiPrintf(L"ReactOS UEFI Boot Manager Initializing...\r\n");
/* Reading the BCD can change this later on */
@@ -1401,49 +1467,190 @@
/* At last, enter the boot selection stage */
SequenceId = 0;
- do
- {
- ContinueLoop = FALSE;
-
- /* Get the list of boot sequences */
- SequenceCount = 0;
- Status = BlGetBootOptionGuidList(BlpApplicationEntry.BcdData,
- BcdBootMgrObjectList_BootSequence,
- &BootSequences,
- &SequenceCount);
- EfiPrintf(L"Count: %d\r\n", SequenceCount);
- EfiStall(1000000);
+ GetEntry = FALSE;
+ BootFailed = FALSE;
+ SequenceList = NULL;
+ BootSequence = NULL;
+ SequenceCount = 0;
+ while (1)
+ {
+ /* We don't have a boot entry nor a sequence ID */
+ BootEntry = NULL;
+ BootOk = FALSE;
+
+ /* Do we have a hardcoded boot sequence set? */
+ if (!(BootSequence) && !(GetEntry))
+ {
+ /* Not yet, read the BCD to see if one is there */
+ Status = BlGetBootOptionGuidList(BlpApplicationEntry.BcdData,
+ BcdBootMgrObjectList_BootSequence,
+ &SequenceList,
+ &SequenceListCount);
+ if (NT_SUCCESS(Status))
+ {
+ /* A GUID list for the boot sequence is set. Extract it */
+ Status = BmGetBootSequence(BcdHandle,
+ SequenceList,
+ SequenceListCount,
+ 0x20000000,
+ &BootSequence,
+ &SequenceCount);
+ if (NT_SUCCESS(Status))
+ {
+ /* Don't get stuck in a loop repeating this sequence */
+ BlRemoveBootOption(BlpApplicationEntry.BcdData,
+ BcdBootMgrObjectList_BootSequence);
+
+ /* But do check if we should persist it */
+ if (PersistBootSequence)
+ {
+ /* Yes -- so go select an entry now */
+ GetEntry = TRUE;
+ }
+ else
+ {
+ /* We shouldn't, so wipe it from the BCD too */
+ Status = BmPurgeOption(BcdHandle,
+ &BmApplicationIdentifier,
+ BcdBootMgrObjectList_BootSequence);
+ if (!NT_SUCCESS(Status))
+ {
+ /* Well that failed */
+ goto LoopQuickie;
+ }
+ }
+ }
+ }
+ else
+ {
+ /* No boot entry sequence for us */
+ BootSequence = NULL;
+ }
+ }
+
+ /* Do we have a sequence active, and are we still processing it? */
+ if ((BootSequence) && ((GetEntry) || (SequenceId < SequenceCount)))
+ {
+ /* Extract the next entry in the sequence */
+ BootEntry = BootSequence[SequenceId];
+ BootSequence[SequenceId] = NULL;
+
+ /* Move to the next entry for next time */
+ SequenceId++;
+
+ /* Unless there won't be a a next time? */
+ if (SequenceId == SequenceCount)
+ {
+ /* Clean up, it's the last entry */
+ BlMmFreeHeap(BootSequence);
+ BootSequence = NULL;
+ }
+ }
+ else
+ {
+ /* Get the selected boot entry from the user */
+ ExitBootManager = FALSE;
+ Status = BmpGetSelectedBootEntry(BcdHandle,
+ &BootEntry,
+ &BootIndex,
+ &ExitBootManager);
+ if (!(NT_SUCCESS(Status)) || (ExitBootManager))
+ {
+ /* Selection failed, or user wants to exit */
+ goto LoopQuickie;
+ }
+ }
+
+ /* Did we have a BCD open? */
+ if (BcdHandle)
+ {
+ /* Close it, we'll be opening a new one */
+ BmCloseDataStore(BcdHandle);
+ BcdHandle = NULL;
+ }
+
+ /* Launch the selected entry */
+ Status = BmpLaunchBootEntry(BootEntry, &BootIndex, 0, TRUE);
+ if (NT_SUCCESS(Status))
+ {
+ /* Boot worked, uncache display and process the bad memory list */
+ BmDisplayStateCached = FALSE;
+ BmpProcessBadMemory();
+ }
+ else
+ {
+ /* Boot failed -- was it user driven? */
+ if (Status != STATUS_CANCELLED)
+ {
+ /* Nope, remember that booting failed */
+ BootFailed = TRUE;
+ goto LoopQuickie;
+ }
+
+ /* Yes -- the display is still valid */
+ BmDisplayStateCached = TRUE;
+ }
+
+ /* Reopen the BCD */
+ Status = BmOpenDataStore(&BcdHandle);
if (!NT_SUCCESS(Status))
{
- //goto GetEntry;
- }
-
+ break;
+ }
+
+ /* Put the BCD options back into our entry */
+ BlReplaceBootOptions(&BlpApplicationEntry, EarlyOptions);
+
+ /* Update our options one more time */
+ Status = BmpUpdateApplicationOptions(BcdHandle);
if (NT_SUCCESS(Status))
{
- continue;
- }
-
+ /* Boot was 100% OK */
+ BootOk = TRUE;
+ }
+
+LoopQuickie:
+ /* Did we have a boot entry? */
+ if (BootEntry)
+ {
+ /* We can destroy it now */
+ BlDestroyBootEntry(BootEntry);
+ }
+
+ /* Is this the success path? */
+ if (NT_SUCCESS(Status))
+ {
+ /* Did we actually boot something? */
+ if (!BootOk)
+ {
+ /* Bope, fail out */
+ break;
+ }
+ }
+
+ /* This is the failure path... should we reboot? */
if (RebootOnError)
{
break;
}
-
- SequenceId++;
- } while (ContinueLoop);
+ };
Failure:
- /* Check if we got here due to an internal error */
- if (BmpInternalBootError)
- {
- /* If XML is available, display the error */
- if (XmlLoaded)
- {
- //BmDisplayDumpError(0, 0);
- //BmErrorPurge();
- }
-
- /* Don't do a fatal error -- return back to firmware */
- goto Quickie;
+ if (!BootFailed)
+ {
+ /* Check if we got here due to an internal error */
+ if (BmpInternalBootError)
+ {
+ /* If XML is available, display the error */
+ if (XmlLoaded)
+ {
+ //BmDisplayDumpError(0, 0);
+ //BmErrorPurge();
+ }
+
+ /* Don't do a fatal error -- return back to firmware */
+ goto Quickie;
+ }
}
/* Log a general fatal error once we're here */
Modified: trunk/reactos/boot/environ/include/bl.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/boot/environ/include/bl.h?…
==============================================================================
--- trunk/reactos/boot/environ/include/bl.h [iso-8859-1] (original)
+++ trunk/reactos/boot/environ/include/bl.h [iso-8859-1] Sat Jan 9 05:39:18 2016
@@ -1514,6 +1514,29 @@
_In_ ULONG Signature
);
+NTSTATUS
+BlUtlInitialize (
+ VOID
+ );
+
+NTSTATUS
+BlUtlRegisterProgressRoutine (
+ VOID
+ );
+
+NTSTATUS
+BlGetApplicationBaseAndSize (
+ _Out_ PVOID* ImageBase,
+ _Out_ PULONG ImageSize
+ );
+
+VOID
+BlDestroyBootEntry (
+ _In_ PBL_LOADED_APPLICATION_ENTRY AppEntry
+ );
+
+/* FIRMWARE UTILITY ROUTINES *************************************************/
+
EFI_STATUS
EfiGetEfiStatusCode(
_In_ NTSTATUS Status
@@ -1524,16 +1547,6 @@
_In_ EFI_STATUS EfiStatus
);
-NTSTATUS
-BlUtlInitialize (
- VOID
- );
-
-NTSTATUS
-BlUtlRegisterProgressRoutine (
- VOID
- );
-
VOID
BlFwReboot (
VOID
@@ -1559,11 +1572,7 @@
VOID
);
-NTSTATUS
-BlGetApplicationBaseAndSize (
- _Out_ PVOID* ImageBase,
- _Out_ PULONG ImageSize
- );
+/* RESOURCE ROUTINES *********************************************************/
PWCHAR
BlResourceFindMessage (
@@ -1714,6 +1723,18 @@
BlAppendBootOptions (
_In_ PBL_LOADED_APPLICATION_ENTRY AppEntry,
_In_ PBL_BCD_OPTION Options
+ );
+
+VOID
+BlRemoveBootOption (
+ _In_ PBL_BCD_OPTION List,
+ _In_ ULONG Type
+ );
+
+NTSTATUS
+BlReplaceBootOptions (
+ _In_ PBL_LOADED_APPLICATION_ENTRY AppEntry,
+ _In_ PBL_BCD_OPTION NewOptions
);
/* BOOT REGISTRY ROUTINES ****************************************************/
Modified: trunk/reactos/boot/environ/lib/bootlib.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/boot/environ/lib/bootlib.c…
==============================================================================
--- trunk/reactos/boot/environ/lib/bootlib.c [iso-8859-1] (original)
+++ trunk/reactos/boot/environ/lib/bootlib.c [iso-8859-1] Sat Jan 9 05:39:18 2016
@@ -436,3 +436,18 @@
*ImageSize = BlpApplicationParameters->ImageSize;
return STATUS_SUCCESS;
}
+
+VOID
+BlDestroyBootEntry (
+ _In_ PBL_LOADED_APPLICATION_ENTRY AppEntry
+ )
+{
+ /* Check if we had allocated BCD options */
+ if (AppEntry->Flags & BL_APPLICATION_ENTRY_BCD_OPTIONS_INTERNAL)
+ {
+ BlMmFreeHeap(AppEntry->BcdData);
+ }
+
+ /* Free the entry itself */
+ BlMmFreeHeap(AppEntry);
+}
Modified: trunk/reactos/boot/environ/lib/misc/bcdopt.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/boot/environ/lib/misc/bcdo…
==============================================================================
--- trunk/reactos/boot/environ/lib/misc/bcdopt.c [iso-8859-1] (original)
+++ trunk/reactos/boot/environ/lib/misc/bcdopt.c [iso-8859-1] Sat Jan 9 05:39:18 2016
@@ -645,3 +645,75 @@
return Status;
}
+VOID
+BlRemoveBootOption (
+ _In_ PBL_BCD_OPTION List,
+ _In_ ULONG Type
+ )
+{
+ PBL_BCD_OPTION Option;
+
+ /* Keep going until the option is gone */
+ while (1)
+ {
+ /* Get the BCD option */
+ Option = MiscGetBootOption(List, Type);
+ if (!Option)
+ {
+ break;
+ }
+
+ /* Pretend it's empty */
+ Option->Empty = TRUE;
+ }
+}
+
+NTSTATUS
+BlReplaceBootOptions (
+ _In_ PBL_LOADED_APPLICATION_ENTRY AppEntry,
+ _In_ PBL_BCD_OPTION NewOptions
+ )
+{
+ NTSTATUS Status;
+ ULONG Size;
+
+ /* Make sure there's something to replace with */
+ if (!NewOptions)
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ /* Check if we already had allocated internal options */
+ if (AppEntry->Flags & BL_APPLICATION_ENTRY_BCD_OPTIONS_INTERNAL)
+ {
+ /* Free them */
+ BlMmFreeHeap(AppEntry->BcdData);
+ }
+
+ /* Reset option flags */
+ AppEntry->Flags &= ~(BL_APPLICATION_ENTRY_BCD_OPTIONS_INTERNAL |
+ BL_APPLICATION_ENTRY_BCD_OPTIONS_EXTERNAL);
+
+ /* Reset the options and set success for now */
+ Status = STATUS_SUCCESS;
+ AppEntry->BcdData = NULL;
+
+ /* Get the size of the new list of options */
+ Size = BlGetBootOptionListSize(NewOptions);
+
+ /* Allocate a copy of the new list */
+ NewOptions = BlMmAllocateHeap(Size);
+ if (!NewOptions)
+ {
+ return STATUS_NO_MEMORY;
+ }
+
+ /* Copy it in */
+ RtlCopyMemory(NewOptions, NewOptions, Size);
+
+ /* Set it as the new set of options and return */
+ AppEntry->Flags |= BL_APPLICATION_ENTRY_BCD_OPTIONS_INTERNAL;
+ AppEntry->BcdData = NewOptions;
+ return Status;
+}
+