[CMLIB/NTOSKRNL]: Move key deletion functions to cmlib, so that UEFI boot library can use them.

[BOOTLIB]: Implement BCD element deletion (bootreg: implement key deletion)
[BOOTMGR]: Implement BL_FATAL_ERROR_BCD_ENTRIES fatal error.
[BOOTMGR]: Stubplement support for memory list data parsing (when memtest.efi will run), and stubplement support for boot persistent data blobs.
[BOOTMGR]: Stubplement boot sequence support, create stub for boot entry population.
[BOOTMGR]: Stubplement boot entry selection, create stub for boot entry enumeration.
Mostly factoring-level changes to get us closer to the needed code paths.

svn path=/trunk/; revision=70609
This commit is contained in:
Alex Ionescu 2016-01-17 21:48:00 +00:00
parent f91d835c5a
commit ba3178b813
12 changed files with 362 additions and 19 deletions

View file

@ -550,6 +550,23 @@ BmFatalErrorEx (
ErrorResourceId = 9002;
break;
case BL_FATAL_ERROR_BCD_ENTRIES:
/* File name is in parameter 1 */
FileName = (PWCHAR)Parameter1;
/* The NTSTATUS code is in parameter 2*/
ErrorStatus = (NTSTATUS)Parameter2;
/* Build the error string */
swprintf(FormatString,
L"\nNo valid entries found in the boot configuration data file %s\n",
FileName);
/* Select the resource ID message */
ErrorResourceId = 9007;
break;
case BL_FATAL_ERROR_BCD_PARSE:
/* File name isin parameter 1 */
@ -1168,7 +1185,22 @@ BmpProcessBadMemory (
VOID
)
{
EfiPrintf(L"Bad page list persistence \r\n");
BL_PD_DATA_BLOB BadMemoryData;
NTSTATUS Status;
/* Try to get the memory data from the memtest application */
BadMemoryData.BlobSize = 0;
BadMemoryData.Data = NULL;
BadMemoryData.DataSize = 0;
Status = BlPdQueryData(&BadMemoryGuid, NULL, &BadMemoryData);
if (Status != STATUS_BUFFER_TOO_SMALL)
{
/* No results, or some other error */
return Status;
}
/* Not yet implemented */
EfiPrintf(L"Bad page list persistence not implemented\r\n");
return STATUS_NOT_IMPLEMENTED;
}
@ -1179,7 +1211,37 @@ BmPurgeOption (
_In_ ULONG Type
)
{
EfiPrintf(L"Key BCD delete not yet implemented\r\n");
HANDLE ObjectHandle;
NTSTATUS Status;
/* Open the object */
Status = BcdOpenObject(BcdHandle, ObjectId, &ObjectHandle);
if (NT_SUCCESS(Status))
{
/* Delete the element */
BcdDeleteElement(ObjectHandle, Type);
/* Close the object and set success */
BiCloseKey(ObjectHandle);
Status = STATUS_SUCCESS;
}
/* Return the result */
return Status;
}
NTSTATUS
BmpPopulateBootEntryList (
_In_ HANDLE BcdHandle,
_In_ PGUID SequenceList,
_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;
}
@ -1193,9 +1255,50 @@ BmGetBootSequence (
_Out_ PULONG SequenceCount
)
{
EfiPrintf(L"Fixed sequences not yet supported\r\n");
PBL_LOADED_APPLICATION_ENTRY* Sequence;
ULONG Count;
NTSTATUS Status;
/* Allocate the sequence list */
Sequence = BlMmAllocateHeap(SequenceListCount * sizeof(*Sequence));
if (!Sequence)
{
return STATUS_NO_MEMORY;
}
/* Populate the sequence list */
Status = BmpPopulateBootEntryList(BcdHandle,
SequenceList,
Flags,
Sequence,
&Count);
if (!NT_SUCCESS(Status))
{
/* Free the list on failure */
BlMmFreeHeap(Sequence);
}
else
{
/* Otherwise, set success and return the list and count */
Status = STATUS_SUCCESS;
*BootSequence = Sequence;
*SequenceCount = Count;
}
/* All done */
return Status;
}
NTSTATUS
BmEnumerateBootEntries (
_In_ HANDLE BcdHandle,
_Out_ PBL_LOADED_APPLICATION_ENTRY **Sequence,
_Out_ PULONG SequenceCount
)
{
EfiPrintf(L"Boot enumeration not yet implemented\r\n");
*Sequence = NULL;
*SequenceCount = 0;
*BootSequence = NULL;
return STATUS_NOT_IMPLEMENTED;
}
@ -1207,8 +1310,69 @@ BmpGetSelectedBootEntry (
_Out_ PBOOLEAN ExitBootManager
)
{
NTSTATUS Status;
PBL_LOADED_APPLICATION_ENTRY* Sequence;
PBL_LOADED_APPLICATION_ENTRY Entry, SelectedEntry;
ULONG Count, BootIndex;
/* Initialize locals */
BootIndex = 0;
Count = 0;
Sequence = NULL;
SelectedEntry = NULL;
/* Enumerate all the boot entries */
Status = BmEnumerateBootEntries(BcdHandle, &Sequence, &Count);
if (!NT_SUCCESS(Status))
{
/* Bail out if we failed */
goto Quickie;
}
/* Check if there are no entries */
if (!Count)
{
/* This is fatal -- kill the system */
Status = STATUS_FILE_INVALID;
BmFatalErrorEx(BL_FATAL_ERROR_BCD_ENTRIES, (ULONG_PTR)L"\\BCD", Status, 0, 0);
goto Quickie;
}
EfiPrintf(L"Boot selection not yet implemented\r\n");
return STATUS_NOT_IMPLEMENTED;
*SelectedBootEntry = NULL;
Quickie:
/* We are done -- did we have a sequence? */
if (Sequence)
{
/* Do we have any boot entries we parsed? */
while (BootIndex < Count)
{
/* Get the current boot entry */
Entry = Sequence[BootIndex];
/* Did we fail, or is is not the selected one? */
if ((Entry) && ((Entry != SelectedEntry) || !(NT_SUCCESS(Status))))
{
/* Destroy it, as it won't be needed */
BlDestroyBootEntry(Entry);
}
else if (Entry == SelectedEntry)
{
/* It's the selected one, return its index */
*EntryIndex = BootIndex;
}
/* Move to the next entry */
BootIndex++;
}
/* Free the sequence of entries */
BlMmFreeHeap(Sequence);
}
/* Return the selection result */
return Status;
}
NTSTATUS

View file

@ -53,6 +53,7 @@ typedef struct _BL_PACKED_BOOT_ERROR
} BL_PACKED_BOOT_ERROR, *PBL_PACKED_BOOT_ERROR;
#define BL_FATAL_ERROR_BCD_READ 0x01
#define BL_FATAL_ERROR_BCD_ENTRIES 0x03
#define BL_FATAL_ERROR_GENERIC 0x04
#define BL_FATAL_ERROR_BCD_PARSE 0x07

View file

@ -245,6 +245,12 @@ BcdOpenObject (
_Out_ PHANDLE ObjectHandle
);
NTSTATUS
BcdDeleteElement (
_In_ HANDLE ObjectHandle,
_In_ ULONG Type
);
NTSTATUS
BcdEnumerateAndUnpackElements (
_In_ HANDLE BcdHandle,

View file

@ -47,6 +47,8 @@
/* DEFINES *******************************************************************/
DEFINE_GUID(BadMemoryGuid, 0x54B8275B, 0xD431, 0x473F, 0xAC, 0xFB, 0xE5, 0x36, 0xA0, 0x84, 0x94, 0xA3);
#define BL_APPLICATION_FLAG_CONVERTED_FROM_EFI 0x01
#define BL_APP_ENTRY_SIGNATURE "BTAPENT"
@ -1142,6 +1144,13 @@ typedef struct _COORD
ULONG Y;
} COORD, *PCOORD;
typedef struct _BL_PD_DATA_BLOB
{
PVOID Data;
ULONG DataSize;
ULONG BlobSize;
} BL_PD_DATA_BLOB, *PBL_PD_DATA_BLOB;
/* INLINE ROUTINES ***********************************************************/
FORCEINLINE
@ -1535,6 +1544,13 @@ BlDestroyBootEntry (
_In_ PBL_LOADED_APPLICATION_ENTRY AppEntry
);
NTSTATUS
BlPdQueryData (
_In_ const GUID* DataGuid,
_In_ PVOID Unknown,
_Inout_ PBL_PD_DATA_BLOB DataBlob
);
/* FIRMWARE UTILITY ROUTINES *************************************************/
EFI_STATUS
@ -1774,6 +1790,11 @@ BiEnumerateSubKeys (
_Out_ PULONG SubKeyCount
);
NTSTATUS
BiDeleteKey (
_In_ HANDLE KeyHandle
);
VOID
BiDereferenceHive (
_In_ HANDLE KeyHandle

View file

@ -20,7 +20,7 @@ BL_LOADED_APPLICATION_ENTRY BlpApplicationEntry;
BOOLEAN BlpLibraryParametersInitialized;
ULONG PdPersistAllocations;
LIST_ENTRY BlBadpListHead;
LIST_ENTRY BlpPdListHead;
/* FUNCTIONS *****************************************************************/
@ -283,7 +283,7 @@ InitializeLibrary (
/* Initialize the boot application persistent data */
PdPersistAllocations = 0;
InitializeListHead(&BlBadpListHead);
InitializeListHead(&BlpPdListHead);
#ifdef BL_TPM_SUPPORT
/* Now setup the security subsystem in phase 1 */
@ -451,3 +451,29 @@ BlDestroyBootEntry (
/* Free the entry itself */
BlMmFreeHeap(AppEntry);
}
NTSTATUS
BlPdQueryData (
_In_ const GUID* DataGuid,
_In_ PVOID Unknown,
_Inout_ PBL_PD_DATA_BLOB DataBlob
)
{
/* Check for invalid or missing parameters */
if (!(DataBlob) ||
!(DataGuid) ||
((DataBlob->BlobSize) && !(DataBlob->Data)))
{
return STATUS_INVALID_PARAMETER;
}
/* Check if there's no persistent data blobs */
if (IsListEmpty(&BlpPdListHead))
{
return STATUS_NOT_FOUND;
}
/* Not yet handled, TODO */
EfiPrintf(L"Boot persistent data not yet implemented\r\n");
return STATUS_NOT_IMPLEMENTED;
}

View file

@ -556,6 +556,66 @@ Quickie:
return Status;
}
NTSTATUS
BcdDeleteElement (
_In_ HANDLE ObjectHandle,
_In_ ULONG Type
)
{
NTSTATUS Status;
HANDLE ElementsHandle, ElementHandle;
WCHAR TypeString[22];
/* Open the elements key */
Status = BiOpenKey(ObjectHandle, L"Elements", &ElementsHandle);
if (NT_SUCCESS(Status))
{
/* Convert the element ID into a string */
if (!_ultow(Type, TypeString, 16))
{
/* Failed to do so */
Status = STATUS_UNSUCCESSFUL;
}
else
{
/* Open the element specifically */
Status = BiOpenKey(ElementHandle, TypeString, &ElementHandle);
if (NT_SUCCESS(Status))
{
/* Delete it */
Status = BiDeleteKey(ElementHandle);
if (NT_SUCCESS(Status))
{
/* No point in closing the handle anymore */
ElementHandle = NULL;
}
}
else
{
/* The element doesn't exist */
Status = STATUS_NOT_FOUND;
}
/* Check if we should close the key */
if (ElementHandle)
{
/* Do it */
BiCloseKey(ElementHandle);
}
}
}
/* Check if we should close the elements handle */
if (ElementsHandle)
{
/* Do it */
BiCloseKey(ElementsHandle);
}
/* Return whatever the result was */
return Status;
}
NTSTATUS
BiEnumerateSubElements (
_In_ HANDLE BcdHandle,

View file

@ -887,3 +887,66 @@ Quickie:
return Status;
}
NTSTATUS
BiDeleteKey (
_In_ HANDLE KeyHandle
)
{
NTSTATUS Status;
PBI_KEY_OBJECT KeyObject;
PHHIVE Hive;
ULONG SubKeyCount, i;
PWCHAR* SubKeyList;
HANDLE SubKeyHandle;
/* Get the key object and hive */
KeyObject = (PBI_KEY_OBJECT)KeyHandle;
Hive = &KeyObject->KeyHive->Hive.Hive;
/* Make sure the hive is writeable */
if (!(KeyObject->KeyHive->Flags & BI_HIVE_WRITEABLE))
{
return STATUS_MEDIA_WRITE_PROTECTED;
}
/* Enumerate all of the subkeys */
Status = BiEnumerateSubKeys(KeyHandle, &SubKeyList, &SubKeyCount);
if ((NT_SUCCESS(Status)) && (SubKeyCount > 0))
{
/* Loop through each one */
for (i = 0; i < SubKeyCount; i++)
{
/* Open a handle to it */
Status = BiOpenKey(KeyHandle, SubKeyList[i], &SubKeyHandle);
if (NT_SUCCESS(Status))
{
/* Recursively call us to delete it */
Status = BiDeleteKey(SubKeyHandle);
if (Status != STATUS_SUCCESS)
{
/* Close the key on failure */
BiCloseKey(SubKeyHandle);
}
}
}
}
/* Check if we had a list of subkeys */
if (SubKeyList)
{
/* Free it */
BlMmFreeHeap(SubKeyList);
}
/* Delete this key cell */
Status = CmpFreeKeyByCell(Hive, KeyObject->KeyCell, TRUE);
if (NT_SUCCESS(Status))
{
/* Mark the hive as requiring a flush */
KeyObject->KeyHive->Flags |= BI_FLUSH_HIVE;
BiCloseKey(KeyHandle);
}
/* All done */
return Status;
}

View file

@ -6,6 +6,7 @@ add_definitions(
list(APPEND SOURCE
cminit.c
cmindex.c
cmkeydel.c
cmname.c
cmvalue.c
hivebin.c

View file

@ -1,14 +1,14 @@
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/config/cmkeydel.c
* PURPOSE: Configuration Manager - Key Body Deletion
* FILE: lib/cmlib/cmkeydel.c
* PURPOSE: Configuration Manager Library - Key Body Deletion
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/
/* INCLUDES ******************************************************************/
#include "ntoskrnl.h"
#include "cmlib.h"
#define NDEBUG
#include "debug.h"
@ -214,6 +214,9 @@ CmpFreeKeyByCell(IN PHHIVE Hive,
HvFreeCell(Hive, CellData->u.KeyNode.ValueList.List);
}
/* FIXME: This leaks the security desriptor! */
DPRINT1("Potentially leaking key security descriptor. Please call CmpFreeSecurityDescriptor");
/* Free the key body itself, and then return our status */
if (!CmpFreeKeyBody(Hive, Cell)) return STATUS_INSUFFICIENT_RESOURCES;
return STATUS_SUCCESS;

View file

@ -671,6 +671,13 @@ CmpCopyKeyValueList(
IN HSTORAGE_TYPE StorageType
);
NTSTATUS
NTAPI
CmpFreeKeyByCell(
IN PHHIVE Hive,
IN HCELL_INDEX Cell,
IN BOOLEAN Unlink
);
/******************************************************************************/

View file

@ -1059,14 +1059,6 @@ DelistKeyBodyFromKCB(
IN BOOLEAN LockHeld
);
NTSTATUS
NTAPI
CmpFreeKeyByCell(
IN PHHIVE Hive,
IN HCELL_INDEX Cell,
IN BOOLEAN Unlink
);
VOID
NTAPI
CmpAcquireTwoKcbLocksExclusiveByKey(

View file

@ -58,7 +58,6 @@ list(APPEND SOURCE
${REACTOS_SOURCE_DIR}/ntoskrnl/config/cmhvlist.c
${REACTOS_SOURCE_DIR}/ntoskrnl/config/cminit.c
${REACTOS_SOURCE_DIR}/ntoskrnl/config/cmkcbncb.c
${REACTOS_SOURCE_DIR}/ntoskrnl/config/cmkeydel.c
${REACTOS_SOURCE_DIR}/ntoskrnl/config/cmlazy.c
${REACTOS_SOURCE_DIR}/ntoskrnl/config/cmmapvw.c
${REACTOS_SOURCE_DIR}/ntoskrnl/config/cmnotify.c