[BOOTMGFW]: Implement BmEnumerateBootEntries.
authorAlex Ionescu <aionescu@gmail.com>
Mon, 18 Jan 2016 05:26:10 +0000 (05:26 +0000)
committerAlex Ionescu <aionescu@gmail.com>
Mon, 18 Jan 2016 05:26:10 +0000 (05:26 +0000)
[BOOTLIB]: Implement BlGetOptionGuid. All BCD option APIs should now be implemented.
[BOOTLIB]: Fix memory corruption + out-of-bounds bugs in BlAppendBootOptions, which made the BCD options remain empty.

svn path=/trunk/; revision=70611

reactos/boot/environ/app/bootmgr/bootmgr.c
reactos/boot/environ/include/bl.h
reactos/boot/environ/lib/misc/bcdopt.c

index 6b2757d..c355897 100644 (file)
@@ -696,7 +696,7 @@ BmCloseDataStore (
     /* Check if boot.ini data needs to be freed */
     if (BmBootIniUsed)
     {
-        EfiPrintf(L"Not handled\r\n");
+        EfiPrintf(L"Boot.ini not handled\r\n");
     }
 
     /* Dereference the hive and close the key */
@@ -756,7 +756,7 @@ BmOpenDataStore (
     if (NT_SUCCESS(Status))
     {
         /* We don't handle custom BCDs yet */
-        EfiPrintf(L"Not handled: %s\r\n", BcdPath);
+        EfiPrintf(L"Custom BCD Not handled: %s\r\n", BcdPath);
         Status = STATUS_NOT_IMPLEMENTED;
         goto Quickie;
     }
@@ -765,7 +765,7 @@ BmOpenDataStore (
     if (BcdDevice->DeviceType == UdpDevice)
     {
         /* Nope. Nope. Nope */
-        EfiPrintf(L"Not handled\r\n");
+        EfiPrintf(L"UDP device Not handled\r\n");
         Status = STATUS_NOT_IMPLEMENTED;
         goto Quickie;
     }
@@ -920,7 +920,7 @@ BlBsdInitializeLog (
 
     /* The BSD is open. Start doing stuff to it */
     EfiPrintf(L"Unimplemented BSD path\r\n");
-    Status =  STATUS_NOT_IMPLEMENTED;
+    Status = STATUS_NOT_IMPLEMENTED;
 
 FailurePath:
     /* Close the BSD if we had it open */
@@ -1239,7 +1239,7 @@ BmpPopulateBootEntryList (
     _Out_ PULONG SequenceCount
     )
 {
-    EfiPrintf(L"Fixed sequences not yet supported\r\n");
+    EfiPrintf(L"Boot population not yet supported\r\n");
     *SequenceCount = 0;
     *BootSequence = NULL;
     return STATUS_NOT_IMPLEMENTED;
@@ -1292,14 +1292,130 @@ BmGetBootSequence (
 NTSTATUS
 BmEnumerateBootEntries (
     _In_ HANDLE BcdHandle,
-    _Out_ PBL_LOADED_APPLICATION_ENTRY **Sequence,
+    _Out_ PBL_LOADED_APPLICATION_ENTRY **BootSequence,
     _Out_ PULONG SequenceCount
     )
 {
-    EfiPrintf(L"Boot enumeration not yet implemented\r\n");
-    *Sequence = NULL;
-    *SequenceCount = 0;
-    return STATUS_NOT_IMPLEMENTED;
+    NTSTATUS Status;
+    ULONG BootIndex, BootIniCount, BootEntryCount, BcdCount;
+    PBL_LOADED_APPLICATION_ENTRY* Sequence;
+    PGUID DisplayOrder;
+    GUID DefaultObject;
+    BOOLEAN UseDisplayList;
+
+    /* Initialize locals */
+    BootIndex = 0;
+
+    /* First try to get the display list, if any */
+    UseDisplayList = TRUE;
+    Status = BlGetBootOptionGuidList(BlpApplicationEntry.BcdData,
+                                     BcdBootMgrObjectList_DisplayOrder,
+                                     &DisplayOrder,
+                                     &BcdCount);
+    if (!NT_SUCCESS(Status))
+    {
+        /* No list, get the default entry instead */
+        Status = BlGetBootOptionGuid(BlpApplicationEntry.BcdData,
+                                     BcdBootMgrObject_DefaultObject,
+                                     &DefaultObject);
+        if (NT_SUCCESS(Status))
+        {
+            /* Set the array to just our entry */
+            UseDisplayList = FALSE;
+            BcdCount = 1;
+            DisplayOrder = &DefaultObject;
+        }
+        else
+        {
+            /* No default list either, return success but no entries */
+            *BootSequence = NULL;
+            *SequenceCount = 0;
+            Status = STATUS_SUCCESS;
+            DisplayOrder = NULL;
+            goto Quickie;
+        }
+    }
+
+    /* Check if boot.ini was used */
+    BootIniCount = 0;
+    if (BmBootIniUsed)
+    {
+        /* Get the entries from it */
+        EfiPrintf(L"Boot.ini not supported\r\n");
+        BootIniCount = 0;//BmBootIniGetEntryCount();
+    }
+
+    /* Allocate an array large enough for the combined boot entries */
+    BootEntryCount = BootIniCount + BcdCount;
+    Sequence = BlMmAllocateHeap(BootEntryCount * sizeof(*Sequence));
+    if (!Sequence)
+    {
+        Status = STATUS_NO_MEMORY;
+        goto Quickie;
+    }
+
+    /* Zero it out */
+    RtlZeroMemory(Sequence, BootEntryCount * sizeof(*Sequence));
+
+    /* Check if we had BCD entries */
+    if (BcdCount)
+    {
+        /* Populate the list of bootable entries */
+        Status = BmpPopulateBootEntryList(BcdHandle,
+                                          DisplayOrder,
+                                          0x800000,
+                                          Sequence,
+                                          &BcdCount);
+        if (!NT_SUCCESS(Status))
+        {
+            /* Bail out */
+            goto Quickie;
+        }
+    }
+
+    /* Check if we had boot.ini entries */
+    if (BootIniCount)
+    {
+        /* TODO */
+        EfiPrintf(L"Boot.ini not supported\r\n");
+    }
+
+    /* Return success and the sequence + count populated */
+    Status = STATUS_SUCCESS;
+    *BootSequence = Sequence;
+    *SequenceCount = BootIniCount + BcdCount;
+
+Quickie:
+    /* Check if we had allocated a GUID list */
+    if ((UseDisplayList) && (DisplayOrder))
+    {
+        /* Free it */
+        BlMmFreeHeap(DisplayOrder);
+    }
+
+    /* Check if this is the failure path */
+    if (!(NT_SUCCESS(Status)) && (Sequence))
+    {
+        /* Loop the remaining boot entries */
+        while (BootIndex < BootEntryCount)
+        {
+            /* Check if it had been allocated */
+            if (Sequence[BootIndex])
+            {
+                /* Free it */
+                BlMmFreeHeap(Sequence[BootIndex]);
+            }
+
+            /* Next*/
+            BootIndex++;
+        }
+
+        /* Free the whole sequence now */
+        BlMmFreeHeap(Sequence);
+    }
+
+    /* All done, return the result */
+    return Status;
 }
 
 NTSTATUS
index 2a1cac4..a03f9d0 100644 (file)
@@ -1721,6 +1721,13 @@ BlGetBootOptionDevice (
     _In_opt_ PBL_BCD_OPTION* ExtraOptions
     );
 
+NTSTATUS
+BlGetBootOptionGuid (
+    _In_ PBL_BCD_OPTION List,
+    _In_ ULONG Type,
+    _Out_ PGUID Value
+    );
+
 NTSTATUS
 BlGetBootOptionGuidList (
     _In_ PBL_BCD_OPTION List,
index a8a7c84..f70995e 100644 (file)
@@ -224,6 +224,44 @@ BlGetBootOptionString (
     return Status;
 }
 
+NTSTATUS
+BlGetBootOptionGuid (
+    _In_ PBL_BCD_OPTION List,
+    _In_ ULONG Type,
+    _Out_ PGUID Value
+    )
+{
+    NTSTATUS Status;
+    PBL_BCD_OPTION Option;
+    PGUID Guid;
+    BcdElementType ElementType;
+
+    /* Make sure this is a BCD_TYPE_OBJECT */
+    ElementType.PackedValue = Type;
+    if (ElementType.Format != BCD_TYPE_OBJECT)
+    {
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    /* Return the data */
+    Option = MiscGetBootOption(List, Type);
+    if (!Option)
+    {
+        /* Set failure if no data exists */
+        Status = STATUS_NOT_FOUND;
+    }
+    else
+    {
+        /* Copy the GUID */
+        Guid = (PGUID)((ULONG_PTR)Option + Option->DataOffset);
+        RtlCopyMemory(Value, Guid, Option->DataSize);
+        Status = STATUS_SUCCESS;
+    }
+
+    /* All good */
+    return Status;
+}
+
 NTSTATUS
 BlGetBootOptionGuidList (
     _In_ PBL_BCD_OPTION List,
@@ -610,7 +648,9 @@ BlAppendBootOptions (
 
     /* Copy the old options, and the ones to be added */
     RtlCopyMemory(NewOptions, CurrentOptions, CurrentSize);
-    RtlCopyMemory(&NewOptions[OptionsSize], Options, OptionsSize);
+    RtlCopyMemory((PVOID)((ULONG_PTR)NewOptions + CurrentSize),
+                  Options,
+                  OptionsSize);
 
     /* We made it! */
     Status = STATUS_SUCCESS;
@@ -626,7 +666,7 @@ BlAppendBootOptions (
     /* Every other option now has to have its offset adjusted */
     do
     {
-        NextOption->NextEntryOffset += OptionsSize;
+        NextOption->NextEntryOffset += CurrentSize;
         NextOption = (PBL_BCD_OPTION)((ULONG_PTR)NewOptions + NextOption->NextEntryOffset);
     } while (NextOption->NextEntryOffset);