Example #1
0
NTSTATUS
FatInitialize (
    VOID
    )
{
    NTSTATUS Status;

    /* Allocate the device table with 2 entries*/
    FatDeviceTableEntries = 2;
    FatDeviceTable = BlMmAllocateHeap(sizeof(PBL_FILE_ENTRY) *
                                      FatDeviceTableEntries);
    if (FatDeviceTable)
    {
        /* Zero it out */
        RtlZeroMemory(FatDeviceTable,
                      sizeof(PBL_FILE_ENTRY) * FatDeviceTableEntries);

        /* Allocate a 512 byte buffer for long file name conversion */
        FatpLongFileName = BlMmAllocateHeap(512);
        Status = FatpLongFileName != NULL ? STATUS_SUCCESS : STATUS_NO_MEMORY;
    }
    else
    {
        /* No memory, fail */
        Status = STATUS_NO_MEMORY;
    }

    /* Return back to caller */
    return Status;
}
Example #2
0
NTSTATUS
BlCopyBootOptions (
    _In_ PBL_BCD_OPTION OptionList,
    _Out_ PBL_BCD_OPTION *CopiedOptions
    )
{
    NTSTATUS Status;
    ULONG OptionSize;
    PBL_BCD_OPTION Options;

    /* Assume no options */
    Status = STATUS_SUCCESS;
    *CopiedOptions = NULL;

    /* Get the size of the list and allocate a copy for it */
    OptionSize = BlGetBootOptionListSize(OptionList);
    Options = BlMmAllocateHeap(OptionSize);
    if (!Options)
    {
        return STATUS_NO_MEMORY;
    }

    /* Make the copy and return it to the caller */
    RtlCopyMemory(Options, OptionList, OptionSize);
    *CopiedOptions = Options;
    return Status;
}
Example #3
0
NTSTATUS
MmBaInitialize (
    VOID
    )
{
    NTSTATUS Status;
    ULONG Size;

    /* Allocate 8 table entries */
    MmBlockAllocatorTableEntries = 8;
    Size = sizeof(BL_BLOCK_DESCRIPTOR) * MmBlockAllocatorTableEntries;
    MmBlockAllocatorTable = BlMmAllocateHeap(Size);
    if (MmBlockAllocatorTable)
    {
        /* Zero them out -- we're all done */
        Status = STATUS_SUCCESS;
        RtlZeroMemory(MmBlockAllocatorTable, Size);
        MmBlockAllocatorInitialized = 1;
    }
    else
    {
        /* Bail out since we're out of memory */
        Status = STATUS_NO_MEMORY;
        MmBlockAllocatorInitialized = 0;
    }

    /* Return initialization status */
    return Status;
}
Example #4
0
File: io.c Project: GYGit/reactos
NTSTATUS
BlpIoInitialize (
    VOID
    )
{
    NTSTATUS Status;
    ULONG Size;

    /* Allocate the I/O table */
    IoMgrRoutineEntries = 4;
    Size = IoMgrRoutineEntries * sizeof(PVOID);
    IoMgrDestroyRoutineTable = BlMmAllocateHeap(Size);
    if (IoMgrDestroyRoutineTable)
    {
        /* Zero it out */
        RtlZeroMemory(IoMgrDestroyRoutineTable, Size);

        /* Initialize the device manager */
        Status = BlpDeviceInitialize();

        /* Initialize the file manager */
        if (NT_SUCCESS(Status))
        {
            Status = BlpFileInitialize();
        }
    }
    else
    {
        /* No memory */
        Status = STATUS_NO_MEMORY;
    }

    /* Return initialization status */
    return Status;
}
Example #5
0
PWCHAR
FileIoCopyFileName (
    _In_ PWCHAR FilePath
    )
{
    PWCHAR Separator, FileCopy;
    ULONG PathSize;

    Separator = wcsrchr(FilePath, '\\');
    if (!Separator)
    {
        return NULL;
    }

    PathSize = wcslen(Separator) * sizeof(WCHAR);

    FileCopy = BlMmAllocateHeap(PathSize);
    if (!FileCopy)
    {
        return NULL;
    }

    wcsncpy(FileCopy, Separator + 1, PathSize / sizeof(WCHAR));
    return FileCopy;
}
Example #6
0
NTSTATUS
BlpMmCreateBlockAllocator (
    VOID
    )
{
    PBL_BLOCK_DESCRIPTOR BlockInfo;
    ULONG BlockId;
    NTSTATUS Status;

    /* If the block allocator isn't initialized, bail out */
    BlockId = -1;
    if (!MmBlockAllocatorInitialized)
    {
        goto Quickie;
    }

    /* Allocate a block descriptor and zero it out */
    BlockInfo = BlMmAllocateHeap(sizeof(*BlockInfo));
    if (!BlockInfo)
    {
        goto Quickie;
    }
    RtlZeroMemory(BlockInfo, sizeof(*BlockInfo));

    /* Setup the block descriptor */
    BlockInfo->Attributes = 0;
    BlockInfo->Type = BlLoaderBlockMemory;
    BlockInfo->Unknown = 1;
    BlockInfo->Unknown2 = 1;
    BlockInfo->Size = PAGE_SIZE;
    BlockInfo->Count = 128;
    BlockInfo->Count2 = 128;
    InitializeListHead(&BlockInfo->ListHead);

    /* Add it to the list of block descriptors */
    Status = BlTblSetEntry(&MmBlockAllocatorTable,
                           &MmBlockAllocatorTableEntries,
                           BlockInfo,
                           &BlockId,
                           MmBapPurgeBlockAllocatorTableEntry);
    if (NT_SUCCESS(Status))
    {
        /* Add the initial reference and store the block ID */
        BlockInfo->ReferenceCount = 1;
        BlockInfo->BlockId = BlockId;
    }

Quickie:
    /* On failure, free the block descriptor */
    if (BlockId == -1)
    {
        BlMmFreeHeap(BlockInfo);
    }

    /* Return the block descriptor ID, or -1 on failure */
    return BlockId;
}
Example #7
0
PVOID
NTAPI
RtlpAllocateMemory (
    _In_ ULONG Bytes,
    _In_ ULONG Tag
    )
{
    UNREFERENCED_PARAMETER(Tag);
    return BlMmAllocateHeap(Bytes);
}
Example #8
0
NTSTATUS
BlpGetBootOptionIntegerList (
    _In_ PBL_BCD_OPTION List,
    _In_ ULONG Type,
    _Out_ PULONGLONG* Value,
    _Out_ PULONGLONG Count,
    _In_ BOOLEAN NoCopy
    )
{
    PBL_BCD_OPTION Option;
    BcdElementType ElementType;
    PULONGLONG ValueCopy;

    /* Make sure this is a BCD_TYPE_INTEGER_LIST */
    ElementType.PackedValue = Type;
    if (ElementType.Format != BCD_TYPE_INTEGER_LIST)
    {
        return STATUS_INVALID_PARAMETER;
    }

    /* Return the data */
    Option = MiscGetBootOption(List, Type);
    if (!Option)
    {
        return STATUS_NOT_FOUND;
    }

    /* Check if a copy should be made of it */
    if (NoCopy)
    {
        /* Nope, return the raw value */
        *Value = (PULONGLONG)((ULONG_PTR)Option + Option->DataOffset);
    }
    else
    {
        /* Allocate a buffer for the copy */
        ValueCopy = BlMmAllocateHeap(Option->DataSize);
        if (!ValueCopy)
        {
            return STATUS_NO_MEMORY;
        }

        /* Copy the data in */
        RtlCopyMemory(ValueCopy,
                      (PVOID)((ULONG_PTR)Option + Option->DataOffset),
                      Option->DataSize);

        /* Return our copy */
        *Value = ValueCopy;
    }

    /* Return count and success */
    *Count = Option->DataSize / sizeof(ULONGLONG);
    return STATUS_SUCCESS;
}
Example #9
0
NTSTATUS
BlGetBootOptionGuidList (
    _In_ PBL_BCD_OPTION List,
    _In_ ULONG Type,
    _Out_ PGUID *Value,
    _In_ PULONG Count
    )
{
    NTSTATUS Status;
    PBL_BCD_OPTION Option;
    PGUID GuidCopy, Guid;
    ULONG GuidCount;
    BcdElementType ElementType;

    /* Make sure this is a BCD_TYPE_OBJECT_LIST */
    ElementType.PackedValue = Type;
    if (ElementType.Format != BCD_TYPE_OBJECT_LIST)
    {
        return STATUS_INVALID_PARAMETER;
    }

    /* Return the data */
    Option = MiscGetBootOption(List, Type);
    if (!Option)
    {
        /* Set failure if no data exists */
        Status = STATUS_NOT_FOUND;
    }
    else
    {
        /* Get the GUIDs and allocate a copy for them */
        Guid = (PGUID)((ULONG_PTR)Option + Option->DataOffset);
        GuidCopy = BlMmAllocateHeap(Option->DataSize);
        if (GuidCopy)
        {
            /* Copy the GUIDs */
            RtlCopyMemory(GuidCopy, Guid, Option->DataSize);

            /* Return the number of GUIDs and the start of the array */
            GuidCount = Option->DataSize / sizeof(GUID);
            *Value = GuidCopy;
            *Count = GuidCount;
            Status = STATUS_SUCCESS;
        }
        else
        {
            /* No memory for the copy */
            Status = STATUS_NO_MEMORY;
        }
    }

    /* All good */
    return Status;
}
Example #10
0
NTSTATUS
BlHtStore (
    _In_ ULONG TableId,
    _In_ PBL_HASH_ENTRY Entry,
    _In_ PVOID Data,
    _In_ ULONG DataSize
    )
{
    PBL_HASH_NODE HashNode;
    NTSTATUS Status;
    PLIST_ENTRY HashLinkHead;
    PBL_HASH_TABLE HashTable;

    /* Check for invalid tablle ID, missing arguments, or malformed entry */
    if ((HtTableSize <= TableId) ||
        !(Entry) ||
        !(Data) ||
        !(Entry->Size) ||
        !(Entry->Value) ||
        !(DataSize) ||
        ((Entry->Flags & BL_HT_VALUE_IS_INLINE) && (Entry->Size != sizeof(ULONG))))
    {
        /* Fail the call */
        Status = STATUS_INVALID_PARAMETER;
        goto Quickie;
    }

    /* Get the hash table for this ID */
    HashTable = HtTableArray[TableId];

    /* Allocate a hash node */
    HashNode = BlMmAllocateHeap(sizeof(*HashNode));
    if (!HashNode)
    {
        Status = STATUS_NO_MEMORY;
        goto Quickie;
    }

    /* Capture all the data*/
    HashNode->Entry.Size = Entry->Size;
    HashNode->Entry.Flags = Entry->Flags;
    HashNode->Entry.Value = Entry->Value;
    HashNode->Value.DataSize = DataSize;
    HashNode->Value.Data = Data;

    /* Insert it into the bucket list and return success */
    HashLinkHead = &HashTable->HashLinks[HashTable->HashFunction(Entry, HashTable->Size)];
    InsertTailList(HashLinkHead, &HashNode->ListEntry);
    Status = STATUS_SUCCESS;

Quickie:
    return Status;
}
Example #11
0
VOID
MmMdFreeGlobalDescriptors (
    VOID
    )
{
    PBL_MEMORY_DESCRIPTOR Descriptor, OldDescriptor;
    ULONG Index = 0;
    PLIST_ENTRY OldFlink, OldBlink;

    /* Make sure we're not int middle of a call using a descriptor */
    if (MmDescriptorCallTreeCount != 1)
    {
        return;
    }

    /* Loop every current global descriptor */
    while (Index < MmGlobalMemoryDescriptorsUsed)
    {
        /* Does it have any valid pageS? */
        OldDescriptor = &MmGlobalMemoryDescriptors[Index];
        if (OldDescriptor->PageCount)
        {
            /* Allocate a copy of it */
            Descriptor = BlMmAllocateHeap(sizeof(*Descriptor));
            if (!Descriptor)
            {
                return;
            }

            /* Save the links */
            OldBlink = OldDescriptor->ListEntry.Blink;
            OldFlink = OldDescriptor->ListEntry.Flink;

            /* Make the copy */
            *Descriptor = *OldDescriptor;

            /* Fix the links */
            OldBlink->Flink = &Descriptor->ListEntry;
            OldFlink->Blink = &Descriptor->ListEntry;

            /* Zero the descriptor */
            RtlZeroMemory(OldDescriptor, sizeof(*OldDescriptor));
        }

        /* Keep going */
        Index++;
    }

    /* All global descriptors freed */
    MmGlobalMemoryDescriptorsUsed = 0;
}
Example #12
0
PVOID
NTAPI
CmpAllocate (
    _In_ SIZE_T Size,
    _In_ BOOLEAN Paged,
    _In_ ULONG Tag
    )
{
    UNREFERENCED_PARAMETER(Paged);
    UNREFERENCED_PARAMETER(Tag);

    /* Call the heap allocator */
    return BlMmAllocateHeap(Size);
}
Example #13
0
NTSTATUS
BlpFileRegisterFileSystem (
    _In_ PBL_FS_INIT_CALLBACK InitCallback,
    _In_ PBL_FS_DESTROY_CALLBACK DestroyCallback,
    _In_ PBL_FS_MOUNT_CALLBACK MountCallback,
    _In_ PBL_FS_PURGE_CALLBACK PurgeCallback,
    _In_ ULONG Flags
    )
{
    PBL_FILE_SYSTEM_ENTRY FsEntry;
    NTSTATUS Status;

    /* Allocate an entry */
    FsEntry = BlMmAllocateHeap(sizeof(*FsEntry));
    if (!FsEntry)
    {
        return STATUS_NO_MEMORY;
    }

    /* Initialize the file system */
    Status = InitCallback();
    if (!NT_SUCCESS(Status))
    {
        BlMmFreeHeap(FsEntry);
        return Status;
    }

    /* Register the callbacks */
    FsEntry->MountCallback = MountCallback;
    FsEntry->DestroyCallback = DestroyCallback;
    FsEntry->InitCallback = InitCallback;
    FsEntry->PurgeCallback = PurgeCallback;

    /* Insert in the right location in the list */
    if (Flags & BL_FS_REGISTER_AT_HEAD_FLAG)
    {
        InsertHeadList(&RegisteredFileSystems, &FsEntry->ListEntry);
    }
    else
    {
        InsertTailList(&RegisteredFileSystems, &FsEntry->ListEntry);
    }

    /* Return */
    return STATUS_SUCCESS;
}
Example #14
0
NTSTATUS
BcdOpenStoreFromFile (
    _In_ PUNICODE_STRING FileName,
    _In_ PHANDLE BcdHandle
    )
{
    ULONG Length;
    PBL_FILE_PATH_DESCRIPTOR FilePath;
    NTSTATUS Status;
    HANDLE LocalHandle;

    /* Assume failure */
    LocalHandle = NULL;

    /* Allocate a path descriptor */
    Length = FileName->Length + sizeof(*FilePath);
    FilePath = BlMmAllocateHeap(Length);
    if (!FilePath)
    {
        return STATUS_NO_MEMORY;
    }

    /* Initialize it */
    FilePath->Version = 1;
    FilePath->PathType = InternalPath;
    FilePath->Length = Length;

    /* Copy the name and NULL-terminate it */
    RtlCopyMemory(FilePath->Path, FileName->Buffer, Length);
    FilePath->Path[Length / sizeof(WCHAR)] = UNICODE_NULL;

    /* Open the BCD */
    Status = BiAddStoreFromFile(FilePath, &LocalHandle);
    if (NT_SUCCESS(Status))
    {
        /* Return the handle on success */
        *BcdHandle = LocalHandle;
    }

    /* Free the descriptor and return the status */
    BlMmFreeHeap(FilePath);
    return Status;
}
Example #15
0
PWCHAR
FileIoCopyParentDirectoryPath (
    _In_ PWCHAR FilePath
    )
{
    ULONG PathSize, PathSizeWithNull;
    PWCHAR Backslash, ParentCopy;

    PathSize = wcslen(FilePath) * sizeof(WCHAR);

    PathSizeWithNull = PathSize + sizeof(UNICODE_NULL);
    if (PathSizeWithNull < PathSize)
    {
        return NULL;
    }

    ParentCopy = BlMmAllocateHeap(PathSizeWithNull);
    if (!ParentCopy)
    {
        return NULL;
    }
    wcsncpy(ParentCopy, FilePath, PathSizeWithNull / sizeof(WCHAR));

    Backslash = wcsrchr(ParentCopy, '\\');
    if (!Backslash)
    {
        BlMmFreeHeap(ParentCopy);
        return NULL;
    }

    if (Backslash == ParentCopy)
    {
        ++Backslash;
    }

    *Backslash = UNICODE_NULL;
    return ParentCopy;
}
Example #16
0
NTSTATUS
BlTblSetEntry (
    _Inout_ PVOID** Table,
    _Inout_ PULONG Count,
    _In_ PVOID Entry,
    _Out_ PULONG EntryIndex,
    _In_ PBL_TBL_SET_ROUTINE Callback
    )
{
    ULONG NewCount;
    NTSTATUS Status = STATUS_SUCCESS;
    ULONG Index = 0;
    PVOID* NewTable;

    /* Make sure all the parameters were specified */
    if (!(Table) || !(*Table) || !(Count) || !(Callback))
    {
        return STATUS_INVALID_PARAMETER;
    }

    /* Read the current table */
    NewTable = *Table;
    NewCount = *Count;

    /* Iterate over it */
    while (Index < NewCount)
    {
        /* Look for a free index */
        if (!NewTable[Index])
        {
            goto SetIndex;
        }

        /* No free index yet, keep going */
        ++Index;
    }

    /* No free index was found, try to purge some entries */
    Index = 0;
    while (Index < NewCount)
    {
        /* Call each purge callback, trying to make space */
        Status = Callback(NewTable[Index]);
        if (NT_SUCCESS(Status))
        {
            /* We should have this slot available now */
            goto SetIndex;
        }

        /* Keep trying to purge more */
        ++Index;
    }

    /* Double the table */
    NewTable = BlMmAllocateHeap(2 * sizeof(PVOID) * NewCount);
    if (!NewTable)
    {
        return STATUS_NO_MEMORY;
    }

    /* Clear the new table, and copy the old entries */
    RtlZeroMemory(&NewTable[NewCount], sizeof(PVOID) * NewCount);
    RtlCopyMemory(NewTable, *Table, sizeof(PVOID) * NewCount);

    /* Free the old table */
    BlMmFreeHeap(*Table);

    /* Return the new table and count */
    *Count = 2 * NewCount;
    *Table = NewTable;

SetIndex:
    /* Set the index and return */
    NewTable[Index] = Entry;
    *EntryIndex = Index;
    return Status;
}
Example #17
0
NTSTATUS
BlpFileInitialize (
    VOID
    )
{
    NTSTATUS Status;

    /* Allocate the file table */
    FileEntries = 16;
    FileTable = BlMmAllocateHeap(sizeof(PBL_FILE_ENTRY) * FileEntries);
    if (!FileTable)
    {
        return STATUS_INVALID_PARAMETER;
    }

    /* Initialize it */
    RtlZeroMemory(FileTable, sizeof(PBL_FILE_ENTRY) * FileEntries);
    InitializeListHead(&RegisteredFileSystems);

#if 0
    /* Initialize the network file system */
    Status = BlpFileRegisterFileSystem(NetRegisterFunctionTable.Init,
                                       NetRegisterFunctionTable.Destroy,
                                       NetRegisterFunctionTable.Mount,
                                       NetRegisterFunctionTable.Purge,
                                       1);
    if (NT_SUCCESS(Status))
    {
        /* Initialize NTFS */
        Status = BlpFileRegisterFileSystem(NtfsRegisterFunctionTable.Init,
                                           NtfsRegisterFunctionTable.Destroy,
                                           NtfsRegisterFunctionTable.Mount,
                                           NtfsRegisterFunctionTable.Purge,
                                           0);
    }

    if (NT_SUCCESS(Status))
#endif
    {
        /* Initialize FAT */
        Status = BlpFileRegisterFileSystem(FatRegisterFunctionTable.Init,
                                           FatRegisterFunctionTable.Destroy,
                                           FatRegisterFunctionTable.Mount,
                                           FatRegisterFunctionTable.Purge,
                                           0);
    }

#if 0
    if (NT_SUCCESS(Status))
    {
        /* Initialize EXFAT (FatPlus) */
        Status = BlpFileRegisterFileSystem(FppRegisterFunctionTable.Init,
                                           FppRegisterFunctionTable.Destroy,
                                           FppRegisterFunctionTable.Mount,
                                           FppRegisterFunctionTable.Purge,
                                           0);
    }

    if (NT_SUCCESS(Status))
    {
        /* Initialize WIM */
        Status = BlpFileRegisterFileSystem(WimRegisterFunctionTable.Init,
                                           WimRegisterFunctionTable.Destroy,
                                           WimRegisterFunctionTable.Mount,
                                           WimRegisterFunctionTable.Purge,
                                           0);
    }

    if (NT_SUCCESS(Status))
    {
        /* Initialize UDFS */
        Status = BlpFileRegisterFileSystem(UdfsRegisterFunctionTable.Init,
                                           UdfsRegisterFunctionTable.Destroy,
                                           UdfsRegisterFunctionTable.Mount,
                                           UdfsRegisterFunctionTable.Purge,
                                           0);
    }
#endif
    if (NT_SUCCESS(Status))
    {
        /* Initialize El-Torito CDFS */
        Status = BlpFileRegisterFileSystem(EtfsRegisterFunctionTable.Init,
                                           EtfsRegisterFunctionTable.Destroy,
                                           EtfsRegisterFunctionTable.Mount,
                                           EtfsRegisterFunctionTable.Purge,
                                           0);
    }

    /* Destroy the file manager if any of the file systems didn't initialize */
    if (!NT_SUCCESS(Status))
    {
        if (FileTable)
        {
            //BlpFileDestroy();
        }
    }
    return Status;
}
Example #18
0
NTSTATUS
BiEnumerateElements (
    _In_ HANDLE BcdHandle,
    _In_ HANDLE ObjectHandle,
    _In_ ULONG RootElementType,
    _In_ ULONG Flags,
    _Out_opt_ PBCD_PACKED_ELEMENT Elements,
    _Inout_ PULONG ElementSize,
    _Out_ PULONG ElementCount
    )
{
    HANDLE ElementsHandle, ElementHandle;
    ULONG TotalLength, RegistryElementDataLength, RemainingLength;
    NTSTATUS Status;
    ULONG i;
    PVOID ElementData, SubObjectList, RegistryElementData;
    BcdElementType ElementType;
    PBCD_PACKED_ELEMENT PreviousElement, ElementsStart;
    ULONG SubElementCount, SubKeyCount, SubObjectCount, ElementDataLength;
    PWCHAR ElementName;
    PWCHAR* SubKeys;

    /* Assume failure */
    *ElementCount = 0;

    /* Initialize all locals that are checked at the end*/
    SubKeys = NULL;
    ElementsHandle = NULL;
    ElementHandle = NULL;
    ElementData = NULL;
    RegistryElementData = NULL;
    PreviousElement = NULL;
    ElementName = NULL;
    SubObjectList = NULL;
    TotalLength = 0;
    ElementDataLength = 0;
    SubObjectCount = 0;
    RemainingLength = 0;
    ElementsStart = Elements;

    /* Open the root object key's elements */
    Status = BiOpenKey(ObjectHandle, L"Elements", &ElementsHandle);
    if (!NT_SUCCESS(Status))
    {
        goto Quickie;
    }

    /* Enumerate all elements */
    Status = BiEnumerateSubKeys(ElementsHandle, &SubKeys, &SubKeyCount);
    if (!NT_SUCCESS(Status))
    {
        goto Quickie;
    }

    /* Iterate over each one */
    for (i = 0; i < SubKeyCount; i++)
    {
        /* Open the element */
        ElementName = SubKeys[i];
        Status = BiOpenKey(ElementsHandle, ElementName, &ElementHandle);
        if (!NT_SUCCESS(Status))
        {
            EfiPrintf(L"ELEMENT ERROR: %lx\r\n", Status);
            EfiStall(100000);
            break;
        }

        /* The name of the element is its data type */
        ElementType.PackedValue = wcstoul(SubKeys[i], NULL, 16);
        if (!(ElementType.PackedValue) || (ElementType.PackedValue == -1))
        {
            EfiPrintf(L"Value invalid\r\n");
            BiCloseKey(ElementHandle);
            ElementHandle = 0;
            continue;
        }

        /* Read the appropriate registry value type for this element */
        Status = BiGetRegistryValue(ElementHandle,
                                    L"Element",
                                    BiConvertElementFormatToValueType(
                                    ElementType.Format),
                                    &RegistryElementData,
                                    &RegistryElementDataLength);
        if (!NT_SUCCESS(Status))
        {
            EfiPrintf(L"Element invalid\r\n");
            break;
        }

        /* Now figure out how much space the converted element will need */
        ElementDataLength = 0;
        Status = BiConvertRegistryDataToElement(ObjectHandle,
                                                RegistryElementData,
                                                RegistryElementDataLength,
                                                ElementType,
                                                NULL,
                                                &ElementDataLength);
        if (Status != STATUS_BUFFER_TOO_SMALL)
        {
            break;
        }

        /* Allocate a buffer big enough for the converted element */
        ElementData = BlMmAllocateHeap(ElementDataLength);
        if (!ElementData)
        {
            Status = STATUS_INSUFFICIENT_RESOURCES;
            break;
        }

        /* And actually convert it this time around */
        Status = BiConvertRegistryDataToElement(ObjectHandle,
                                                RegistryElementData,
                                                RegistryElementDataLength,
                                                ElementType,
                                                ElementData,
                                                &ElementDataLength);
        if (!NT_SUCCESS(Status))
        {
            break;
        }

        /* Safely add space for the packed element header */
        Status = RtlULongAdd(TotalLength,
                             FIELD_OFFSET(BCD_PACKED_ELEMENT, Data),
                             &TotalLength);
        if (!NT_SUCCESS(Status))
        {
            break;
        }

        /* Safely add space for the data of the element itself */
        Status = RtlULongAdd(TotalLength, ElementDataLength, &TotalLength);
        if (!NT_SUCCESS(Status))
        {
            break;
        }

        /* One more element */
        ++*ElementCount;

        /* See how much space we were given */
        RemainingLength = *ElementSize;
        if (RemainingLength >= TotalLength)
        {
            /* Set the next pointer */
            Elements->NextEntry = (PBCD_PACKED_ELEMENT)((ULONG_PTR)ElementsStart + TotalLength);

            /* Fill this one out */
            Elements->RootType.PackedValue = RootElementType;
            Elements->Version = 1;
            Elements->Type = ElementType.PackedValue;
            Elements->Size = ElementDataLength;

            /* Add the data */
            RtlCopyMemory(Elements->Data, ElementData, ElementDataLength);
            RemainingLength -= TotalLength;

            /* Move to the next element on the next pass */
            PreviousElement = Elements;
            Elements = Elements->NextEntry;
        }
        else
        {
            /* We're out of space */
            RemainingLength = 0;
        }

        /* Are we enumerating devices, and is this a device? */
        if ((Flags & BCD_ENUMERATE_FLAG_DEVICES) &&
            (ElementType.Format == BCD_TYPE_DEVICE))
        {
            /* Yep, so go inside to enumerate it */
            Status = BiEnumerateSubElements(BcdHandle,
                                            ElementData,
                                            ElementType.PackedValue,
                                            Flags,
                                            &Elements,
                                            &ElementDataLength,
                                            &SubElementCount);
            if ((NT_SUCCESS(Status)) || (Status == STATUS_BUFFER_TOO_SMALL))
            {
                /* Safely add the length of the sub elements */
                Status = RtlULongAdd(TotalLength,
                                     ElementDataLength,
                                     &TotalLength);
                if (!NT_SUCCESS(Status))
                {
                    break;
                }

                /* Add the sub elements to the total */
                *ElementCount += SubElementCount;

                /* See if we have enough space*/
                if (*ElementSize >= TotalLength)
                {
                    /* Were there any subelements? */
                    if (SubElementCount)
                    {
                        /* Update to keep track of these new subelements */
                        ElementDataLength = *ElementSize - TotalLength;

                        /* Link the subelements into the chain */
                        PreviousElement = Elements;
                        PreviousElement->NextEntry =
                            (PBCD_PACKED_ELEMENT)((ULONG_PTR)ElementsStart +
                                                  TotalLength);
                        Elements = PreviousElement->NextEntry;
                    }
                }
                else
                {
                    /* We're out of space */
                    ElementDataLength = 0;
                }
            }
            else if ((Status != STATUS_NOT_FOUND) &&
                     (Status != STATUS_OBJECT_NAME_NOT_FOUND))
            {
                /* Fatal error trying to read the data, so fail */
                break;
            }
        }
        else if ((Flags & BCD_ENUMERATE_FLAG_DEEP) &&
                 (ElementType.PackedValue == BcdLibraryObjectList_InheritedObjects))
        {
            /* Inherited objects are requsted, so allocate a buffer for them */
            SubObjectList = BlMmAllocateHeap(ElementDataLength);
            if (!SubObjectList)
            {
                Status = STATUS_INSUFFICIENT_RESOURCES;
                break;
            }

            /* Copy the elements into the list. They are arrays of GUIDs */
            RtlCopyMemory(SubObjectList, ElementData, ElementDataLength);
            SubObjectCount = ElementDataLength / sizeof(GUID);
        }

        /* Free our local buffers */
        BlMmFreeHeap(ElementData);
        BlMmFreeHeap(RegistryElementData);
        ElementData = NULL;
        RegistryElementData = NULL;

        /* Close the key */
        BiCloseKey(ElementHandle);
        ElementHandle = NULL;
        ElementName = NULL;
    }

    /* Did we end up here with a sub object list after successful loop parsing? */
    if ((i != 0) && (i == SubKeyCount) && (SubObjectList))
    {
        /* We will actually enumerate it now, at the end */
        Status = BiEnumerateSubObjectElements(BcdHandle,
                                              SubObjectList,
                                              SubObjectCount,
                                              Flags,
                                              Elements,
                                              &RemainingLength,
                                              &SubElementCount);
        if ((NT_SUCCESS(Status)) || (Status == STATUS_BUFFER_TOO_SMALL))
        {
            /* Safely add the length of the sub elements */
            Status = RtlULongAdd(TotalLength, RemainingLength, &TotalLength);
            if ((NT_SUCCESS(Status)) && (SubElementCount))
            {
                /* Add the sub elements to the total */
                *ElementCount += SubElementCount;

                /* Don't touch PreviousElement anymore */
                PreviousElement = NULL;
            }
        }
    }

Quickie:
    /* Free the sub object list, if any */
    if (SubObjectList)
    {
        BlMmFreeHeap(SubObjectList);
    }

    /* Free any local element data */
    if (ElementData)
    {
        BlMmFreeHeap(ElementData);
    }

    /* Free any local registry data */
    if (RegistryElementData)
    {
        BlMmFreeHeap(RegistryElementData);
    }

    /* Close the handle if still opened */
    if (ElementHandle)
    {
        BiCloseKey(ElementHandle);
    }

    /* Terminate the last element, if any */
    if (PreviousElement)
    {
        PreviousElement->NextEntry = NULL;
    }

    /* Close the root handle if still opened */
    if (ElementsHandle)
    {
        BiCloseKey(ElementsHandle);
    }

    /* Set  failure code if out of space */
    if (*ElementSize < TotalLength)
    {
        Status = STATUS_BUFFER_TOO_SMALL;
    }

    /* Other errors will send a notification error */
    if (!(NT_SUCCESS(Status)) && (Status != STATUS_BUFFER_TOO_SMALL))
    {
        BiNotifyEnumerationError(ObjectHandle, ElementName, Status);
    }

    /* Finally free the subkeys array */
    if (SubKeys)
    {
        BlMmFreeHeap(SubKeys);
    }

    /* And return the required, final length and status */
    *ElementSize = TotalLength;
    return Status;
}
Example #19
0
NTSTATUS
BlGetBootOptionString (
    _In_ PBL_BCD_OPTION List,
    _In_ ULONG Type,
    _Out_ PWCHAR* Value
    )
{
    NTSTATUS Status;
    PBL_BCD_OPTION Option;
    PWCHAR String, StringCopy;
    ULONG StringLength;
    BcdElementType ElementType;
    //PGUID AppIdentifier;

    /* Make sure this is a BCD_STRING */
    ElementType.PackedValue = Type;
    if (ElementType.Format != BCD_TYPE_STRING)
    {
        return STATUS_INVALID_PARAMETER;
    }

    /* Return the data */
    Option = MiscGetBootOption(List, Type);
    if (Option)
    {
        /* Extract the string */
        String = (PWCHAR)((ULONG_PTR)Option + Option->DataOffset);
        Status = STATUS_SUCCESS;
    }
    else
    {
        /* No string is present */
        String = NULL;
        Status = STATUS_NOT_FOUND;
    }

    /* Compute the data size */
    StringLength = Option->DataSize / sizeof(WCHAR);

#ifdef _SECURE_BOOT_
    /* Filter out SecureBoot Options */
    AppIdentifier = BlGetApplicationIdentifier();
    Status = BlpBootOptionCallbackString(AppIdentifier, Type, String, StringLength, &String, &StringLength);
#else
#endif

    /* Make sure we have a valid, non-filtered string */
    if (NT_SUCCESS(Status))
    {
        /* Check if we have space for one more character */
        Status = RtlULongAdd(StringLength, 1, &StringLength);
        if (NT_SUCCESS(Status))
        {
            /* Check if it's safe to multiply by two */
            Status = RtlULongMult(StringLength, sizeof(WCHAR), &StringLength);
            if (NT_SUCCESS(Status))
            {
                /* Allocate a copy for the string */
                StringCopy = BlMmAllocateHeap(StringLength);
                if (StringCopy)
                {
                    /* NULL-terminate it */
                    RtlCopyMemory(StringCopy,
                                  String,
                                  StringLength - sizeof(UNICODE_NULL));
                    StringCopy[StringLength] = UNICODE_NULL;
                    *Value = StringCopy;
                    Status = STATUS_SUCCESS;
                }
                else
                {
                    /* No memory, fail */
                    Status = STATUS_NO_MEMORY;
                }
            }
        }
    }

    /* All done */
    return Status;
}
Example #20
0
NTSTATUS
BiLoadHive (
    _In_ PBL_FILE_PATH_DESCRIPTOR FilePath,
    _Out_ PHANDLE HiveHandle
    )
{
    ULONG DeviceId;
    PHBASE_BLOCK BaseBlock, NewBaseBlock;
    PBI_KEY_OBJECT KeyObject;
    PBI_KEY_HIVE BcdHive;
    PBL_DEVICE_DESCRIPTOR BcdDevice;
    ULONG PathLength, DeviceLength, HiveSize, HiveLength, NewHiveSize;
    PWCHAR HiveName, LogName;
    BOOLEAN HaveWriteAccess;
    NTSTATUS Status;
    PVOID LogData;
    PHHIVE Hive;
    UNICODE_STRING KeyString;
    PCM_KEY_NODE RootNode;
    HCELL_INDEX CellIndex;

    /* Initialize variables */
    DeviceId = -1;
    BaseBlock = NULL;
    BcdHive = NULL;
    KeyObject = NULL;
    LogData = NULL;
    LogName = NULL;

    /* Initialize the crypto seed */
    if (!BiHiveHashLibraryInitialized)
    {
        HvSymcryptSeed = 0x82EF4D887A4E55C5;
        BiHiveHashLibraryInitialized = TRUE;
    }

    /* Extract and validate the input path */
    BcdDevice = (PBL_DEVICE_DESCRIPTOR)&FilePath->Path;
    PathLength = FilePath->Length;
    DeviceLength = BcdDevice->Size;
    HiveName = (PWCHAR)((ULONG_PTR)BcdDevice + BcdDevice->Size);
    if (PathLength <= DeviceLength)
    {
        /* Doesn't make sense, bail out */
        Status = STATUS_INVALID_PARAMETER;
        goto Quickie;
    }

    /* Attempt to open the underlying device for RW access */
    HaveWriteAccess = TRUE;
    Status = BlpDeviceOpen(BcdDevice,
                           BL_DEVICE_READ_ACCESS | BL_DEVICE_WRITE_ACCESS,
                           0,
                           &DeviceId);
    if (!NT_SUCCESS(Status))
    {
        /* Try for RO access instead */
        HaveWriteAccess = FALSE;
        Status = BlpDeviceOpen(BcdDevice, BL_DEVICE_READ_ACCESS, 0, &DeviceId);
        if (!NT_SUCCESS(Status))
        {
            /* No access at all -- bail out */
            goto Quickie;
        }
    }

    /* Now try to load the hive on disk */
    Status = BlImgLoadImageWithProgress2(DeviceId,
                                         BlLoaderRegistry,
                                         HiveName,
                                         (PVOID*)&BaseBlock,
                                         &HiveSize,
                                         0,
                                         FALSE,
                                         NULL,
                                         NULL);
    if (!NT_SUCCESS(Status))
    {
        EfiPrintf(L"Hive read failure: % lx\r\n", Status);
        goto Quickie;
    }

    /* Allocate a hive structure */
    BcdHive = BlMmAllocateHeap(sizeof(*BcdHive));
    if (!BcdHive)
    {
        Status = STATUS_NO_MEMORY;
        goto Quickie;
    }

    /* Initialize it */
    RtlZeroMemory(BcdHive, sizeof(*BcdHive));
    BcdHive->BaseBlock = BaseBlock;
    BcdHive->HiveSize = HiveSize;
    if (HaveWriteAccess)
    {
        BcdHive->Flags |= BI_HIVE_WRITEABLE;
    }

    /* Make sure the hive was at least one bin long */
    if (HiveSize < sizeof(*BaseBlock))
    {
        Status = STATUS_REGISTRY_CORRUPT;
        goto Quickie;
    }

    /* Make sure the hive contents are at least one bin long */
    HiveLength = BaseBlock->Length;
    if (BaseBlock->Length < sizeof(*BaseBlock))
    {
        Status = STATUS_REGISTRY_CORRUPT;
        goto Quickie;
    }

    /* Validate the initial bin (the base block) */
    if (!HvIsInPlaceBaseBlockValid(BaseBlock))
    {
        EfiPrintf(L"Recovery not implemented\r\n");
        Status = STATUS_REGISTRY_CORRUPT;
        goto Quickie;
    }

    /* Check if there's log recovery that needs to happen */
    if (BaseBlock->Sequence1 != BaseBlock->Sequence2)
    {
        EfiPrintf(L"Log fix not implemented: %lx %lx\r\n");
        Status = STATUS_REGISTRY_CORRUPT;
        goto Quickie;
    }

    /*
     * Check if the whole hive doesn't fit in the buffer.
     * Note: HiveLength does not include the size of the baseblock itself
     */
    if (HiveSize < (HiveLength + sizeof(*BaseBlock)))
    {
        EfiPrintf(L"Need bigger hive buffer path\r\n");

        /* Allocate a slightly bigger buffer */
        NewHiveSize = HiveLength + sizeof(*BaseBlock);
        Status = MmPapAllocatePagesInRange((PVOID*)&NewBaseBlock,
                                           BlLoaderRegistry,
                                           NewHiveSize >> PAGE_SHIFT,
                                           0,
                                           0,
                                           NULL,
                                           0);
        if (!NT_SUCCESS(Status))
        {
            goto Quickie;
        }

        /* Copy the current data in there */
        RtlCopyMemory(NewBaseBlock, BaseBlock, HiveSize);

        /* Free the old data */
        EfiPrintf(L"Leaking old hive buffer\r\n");
        //MmPapFreePages(BaseBlock, 1);

        /* Update our pointers */
        BaseBlock = NewBaseBlock;
        HiveSize = NewHiveSize;
        BcdHive->BaseBlock = BaseBlock;
        BcdHive->HiveSize = HiveSize;
    }
Example #21
0
NTSTATUS
DsppLoadFontFile (
    _In_ PWCHAR FontFileName
    )
{
    PBL_DEVICE_DESCRIPTOR FontDevice;
    NTSTATUS Status;
    ULONG NameLength, DirectoryLength, TotalLength;
    PWCHAR FontPath, FontDirectory;
    BL_LIBRARY_PARAMETERS LibraryParameters;
    BOOLEAN CustomDirectory, CustomDevice;

    /* Initialize locals */
    CustomDirectory = TRUE;
    CustomDevice = TRUE;
    FontDevice = NULL;
    FontPath = NULL;
    FontDirectory = NULL;

    /* Check if a custom font path should be used */
    Status = BlGetBootOptionString(BlpApplicationEntry.BcdData,
                                   BcdLibraryString_FontPath,
                                   &FontDirectory);
    if (!NT_SUCCESS(Status))
    {
        /* Nope, use the one configured by the library */
        CustomDirectory = FALSE;
        RtlCopyMemory(&LibraryParameters,
                      &BlpLibraryParameters,
                      sizeof(LibraryParameters)),
        FontDirectory = LibraryParameters.FontBaseDirectory;
    }

    /* Do we still not have a font directory? */
    if (!FontDirectory)
    {
        /* Use the boot device and boot directory */
        FontDevice = BlpBootDevice;
        FontDirectory = L"\\EFI\\Microsoft\\Boot\\Fonts";
        CustomDevice = FALSE;
    }
    else
    {
        /* Otherwise, if we have a font directory, what device is the app on? */
        Status = BlGetBootOptionDevice(BlpApplicationEntry.BcdData,
                                       BcdLibraryDevice_ApplicationDevice,
                                       &FontDevice,
                                       NULL);
        if (!NT_SUCCESS(Status))
        {
            /* If we don't know the device, we can't open the path */
            goto Quickie;
        }
    }

    /* Figure out the length of the file name, and of the directory */
    NameLength = wcslen(FontFileName);
    DirectoryLength = wcslen(FontDirectory);

    /* Safely add them up*/
    Status = RtlULongAdd(NameLength, DirectoryLength, &TotalLength);
    if (!NT_SUCCESS(Status))
    {
        goto Quickie;
    }

    /* Convert to bytes */
    Status = RtlULongLongToULong(TotalLength * sizeof(WCHAR), &TotalLength);
    if (!NT_SUCCESS(Status))
    {
        goto Quickie;
    }

    /* Add a terminating NUL */
    Status = RtlULongAdd(TotalLength, sizeof(UNICODE_NULL), &TotalLength);
    if (!NT_SUCCESS(Status))
    {
        goto Quickie;
    }

    /* Allocate the final buffer for it */
    FontPath = BlMmAllocateHeap(TotalLength);
    if (!FontPath)
    {
        Status = STATUS_NO_MEMORY;
        goto Quickie;
    }

    /* Concatenate the directory with the file name */
    wcscpy(FontPath, FontDirectory);
    wcscat(FontPath, FontFileName);

    /* Try to load this font */
    Status = BfLoadFontFile(FontDevice, FontPath);

Quickie:
    /* Check if we had a custom font device allocated and free it */
    if ((CustomDevice) && (FontDevice))
    {
        BlMmFreeHeap(FontDevice);
    }

    /* Check if we had a custom font directory allocated and free it */
    if ((FontDirectory) && (CustomDirectory))
    {
        BlMmFreeHeap(FontDirectory);
    }

    /* Check if we had allocated a font path and free it */
    if (FontPath)
    {
        BlMmFreeHeap(FontPath);
    }

    /* Return back */
    return Status;
}
Example #22
0
NTSTATUS
DsppInitialize (
    _In_ ULONG Flags
    )
{
    BL_LIBRARY_PARAMETERS LibraryParameters = BlpLibraryParameters;
    BOOLEAN NoGraphics, HighestMode;
    NTSTATUS Status;
    PBL_DISPLAY_MODE DisplayMode;
    ULONGLONG GraphicsResolution;
    PBL_GRAPHICS_CONSOLE GraphicsConsole;
    PBL_TEXT_CONSOLE TextConsole, RemoteConsole;

    /* Initialize font data */
    BfiCachedStrikeData = 0;
    InitializeListHead(&BfiDeferredListHead);
    InitializeListHead(&BfiFontFileListHead);

    /* Allocate the font rectangle */
    BfiGraphicsRectangle = BlMmAllocateHeap(90);
    if (!BfiGraphicsRectangle)
    {
        return STATUS_NO_MEMORY;
    }

    /* Display re-initialization not yet handled */
    if (LibraryParameters.LibraryFlags & BL_LIBRARY_FLAG_REINITIALIZE_ALL)
    {
        EfiPrintf(L"Display path not handled\r\n");
        return STATUS_NOT_SUPPORTED;
    }

    /* Check if no graphics console is needed */
    if ((Flags & BL_LIBRARY_FLAG_NO_GRAPHICS_CONSOLE) ||
        (DsppGraphicsDisabledByBcd()))
    {
        /* Remember this */
        NoGraphics = TRUE;
    }
    else
    {
        /* No graphics -- remember this */
        NoGraphics = FALSE;
    }

    /* On first load, we always initialize a graphics display */
    GraphicsConsole = NULL;
    if (!(Flags & BL_LIBRARY_FLAG_REINITIALIZE_ALL) || !(NoGraphics))
    {
        /* Default to mode 0 (1024x768) */
        DisplayMode = &ConsoleGraphicalResolutionList[0];

        /* Check what resolution to use*/
        Status = BlGetBootOptionInteger(BlpApplicationEntry.BcdData,
                                        BcdLibraryInteger_GraphicsResolution,
                                        &GraphicsResolution);
        if (NT_SUCCESS(Status))
        {
            ConsoleGraphicalResolutionListFlags |= BL_DISPLAY_GRAPHICS_FORCED_VIDEO_MODE_FLAG;
            EfiPrintf(L"Display selection not yet handled\r\n");
            return STATUS_NOT_IMPLEMENTED;
        }

        /* Check if the highest mode should be forced */
        Status = BlGetBootOptionBoolean(BlpApplicationEntry.BcdData,
                                        BcdLibraryBoolean_GraphicsForceHighestMode,
                                        &HighestMode);
        if (NT_SUCCESS(Status))
        {
            ConsoleGraphicalResolutionListFlags |= BL_DISPLAY_GRAPHICS_FORCED_HIGH_RES_MODE_FLAG;
            EfiPrintf(L"High res mode not yet handled\r\n");
            return STATUS_NOT_IMPLEMENTED;
        }

        /* Do we need graphics mode after all? */
        if (!NoGraphics)
        {
            /* Yep -- go allocate it */
            GraphicsConsole = BlMmAllocateHeap(sizeof(*GraphicsConsole));
            if (GraphicsConsole)
            {
                /* Construct it */
                Status = ConsoleGraphicalConstruct(GraphicsConsole);
                if (!NT_SUCCESS(Status))
                {
                    EfiPrintf(L"GFX FAILED: %lx\r\n", Status);
                    BlMmFreeHeap(GraphicsConsole);
                    GraphicsConsole = NULL;
                }
                else
                {
                    /* TEST */
                    RtlFillMemory(GraphicsConsole->FrameBuffer, GraphicsConsole->FrameBufferSize, 0x55);
                }
            }
        }

        /* Are we using something else than the default mode? */
        if (DisplayMode != &ConsoleGraphicalResolutionList[0])
        {
            EfiPrintf(L"Display path not handled\r\n");
            return STATUS_NOT_SUPPORTED;
        }

        /* Mask out all the flags now */
        ConsoleGraphicalResolutionListFlags &= ~(BL_DISPLAY_GRAPHICS_FORCED_VIDEO_MODE_FLAG |
                                                 BL_DISPLAY_GRAPHICS_FORCED_HIGH_RES_MODE_FLAG);
    }

    /* Do we have a graphics console? */
    TextConsole = NULL;
    if (!GraphicsConsole)
    {
        /* Nope -- go allocate a text console */
        TextConsole = BlMmAllocateHeap(sizeof(*TextConsole));
        if (TextConsole)
        {
            /* Construct it */
            Status = ConsoleTextLocalConstruct(TextConsole, TRUE);
            if (!NT_SUCCESS(Status))
            {
                BlMmFreeHeap(TextConsole);
                TextConsole = NULL;
            }
        }
    }

    /* Initialize all globals to NULL */
    DspRemoteInputConsole = NULL;
    DspTextConsole = NULL;
    DspGraphicalConsole = NULL;

    /* If we don't have a text console, go get a remote console */
    RemoteConsole = NULL;
    if (!TextConsole)
    {
        ConsoleCreateRemoteConsole(&RemoteConsole);
    }

    /* Do we have a remote console? */
    if (!RemoteConsole)
    {
        /* Nope -- what about a graphical one? */
        if (GraphicsConsole)
        {
            /* Yes, use it for both graphics and text */
            DspGraphicalConsole = GraphicsConsole;
            DspTextConsole = GraphicsConsole;
        }
        else if (TextConsole)
        {
            /* Nope, but we have a text console */
            DspTextConsole = TextConsole;
        }

        /* Console has been setup */
        return STATUS_SUCCESS;
    }

    /* We have a remote console -- have to figure out how to use it*/
    EfiPrintf(L"Display path not handled\r\n");
    return STATUS_NOT_SUPPORTED;
}
Example #23
0
NTSTATUS
ConsoleEfiTextFindModeFromAllowed (
    _In_ SIMPLE_TEXT_OUTPUT_INTERFACE *TextProtocol,
    _In_ PBL_DISPLAY_MODE SupportedModes,
    _In_ ULONG MaxIndex,
    _Out_ PULONG SupportedMode
    )
{
    EFI_SIMPLE_TEXT_OUTPUT_MODE ModeInfo;
    ULONG MaxMode, MaxQueriedMode, Mode, i, MatchingMode;
    UINTN HRes, VRes;
    ULONGLONG ModeListSize;
    PBL_DISPLAY_MODE ModeEntry, ModeList, SupportedModeEntry;
    NTSTATUS Status;

    /* Read information on the current mode */
    EfiConOutReadCurrentMode(TextProtocol, &ModeInfo);

    /* Figure out the max mode, and how many modes we'll have to read */
    MaxMode = ModeInfo.MaxMode;
    ModeListSize = sizeof(*ModeEntry) * ModeInfo.MaxMode;
    if (ModeListSize > MAXULONG)
    {
        return STATUS_INTEGER_OVERFLOW;
    }

    /* Allocate a list for all the supported EFI modes */
    ModeList = BlMmAllocateHeap(ModeListSize);
    if (!ModeList)
    {
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    /* Scan all the EFI modes */
    EfiPrintf(L"Scanning through %d modes\r\n", MaxMode);
    for (MaxQueriedMode = 0, Mode = 0; Mode < MaxMode; Mode++)
    {
        /* Query information on this mode */
        ModeEntry = &ModeList[MaxQueriedMode];
        if (NT_SUCCESS(EfiConOutQueryMode(TextProtocol,
                                          Mode,
                                          &HRes,
                                          &VRes)))
        {
            /* This mode was succesfully queried. Save the data */
            EfiPrintf(L"EFI Firmware Supported Mode %d is H: %d V: %d\r\n", Mode, HRes, VRes);
            ModeEntry->HRes = HRes;
            ModeEntry->VRes = VRes;
            ModeEntry->HRes2 = HRes;
            MaxQueriedMode = Mode + 1;
        }
    }

    /* Loop all the supported mode entries */
    for (i = 0; i < MaxIndex; i++)
    {
        /* Loop all the UEFI queried modes */
        SupportedModeEntry = &SupportedModes[i];
        for (MatchingMode = 0; MatchingMode < MaxQueriedMode; MatchingMode++)
        {
            /* Check if the UEFI mode is compatible with our supported mode */
            ModeEntry = &ModeList[MatchingMode];
            EfiPrintf(L"H1: %d V1: %d - H2: %d - V2: %d\r\n", ModeEntry->HRes, ModeEntry->VRes, SupportedModeEntry->HRes, SupportedModeEntry->VRes);
            if ((ModeEntry->HRes == SupportedModeEntry->HRes) &&
                (ModeEntry->VRes == SupportedModeEntry->VRes))
            {
                /* Yep -- free the mode list and return this mode */
                BlMmFreeHeap(ModeList);
                *SupportedMode = MatchingMode;
                return STATUS_SUCCESS;
            }
        }
    }

    /* We can't do anything -- there are no matching modes */
    Status = STATUS_UNSUCCESSFUL;
    BlMmFreeHeap(ModeList);
    return Status;
}
Example #24
0
NTSTATUS
BcdEnumerateAndUnpackElements (
    _In_ HANDLE BcdHandle,
    _In_ HANDLE ObjectHandle,
    _Out_opt_ PBCD_ELEMENT Elements,
    _Inout_ PULONG ElementSize,
    _Out_ PULONG ElementCount
    )
{
    PVOID LocalElements;
    NTSTATUS Status;
    ULONG LocalElementCount, LocalElementSize;

    /* Make sure required parameters are there */
    if (!(ElementSize) || !(ElementCount) || ((Elements) && (!*ElementSize)))
    {
        return STATUS_INVALID_PARAMETER;
    }

    /* Set initial count to zero */
    *ElementCount = 0;

    /* Do the initial enumeration to figure out the size required */
    LocalElementSize = 0;
    LocalElementCount = 0;
    Status = BiEnumerateElements(BcdHandle,
                                 ObjectHandle,
                                 0,
                                 BCD_ENUMERATE_FLAG_IN_ORDER |
                                 BCD_ENUMERATE_FLAG_DEVICES |
                                 BCD_ENUMERATE_FLAG_DEEP,
                                 NULL,
                                 &LocalElementSize,
                                 &LocalElementCount);
    if (Status != STATUS_BUFFER_TOO_SMALL)
    {
        return Status;
    }

    /* Now allocate a buffer large enough to hold them */
    LocalElements = BlMmAllocateHeap(LocalElementSize);
    if (!LocalElements)
    {
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    /* Zero out the array and do the real enumeration this time around */
    RtlZeroMemory(LocalElements, LocalElementSize);
    Status = BiEnumerateElements(BcdHandle,
                                 ObjectHandle,
                                 0,
                                 BCD_ENUMERATE_FLAG_IN_ORDER |
                                 BCD_ENUMERATE_FLAG_DEVICES |
                                 BCD_ENUMERATE_FLAG_DEEP,
                                 LocalElements,
                                 &LocalElementSize,
                                 &LocalElementCount);
    if (!NT_SUCCESS(Status))
    {
        return Status;
    }

    /* Now we know the real count */
    *ElementCount = LocalElementCount;

    /* Now unpack the data */
    Status = BiConvertBcdElements(LocalElements,
                                  Elements,
                                  ElementSize,
                                  &LocalElementCount);
    if (NT_SUCCESS(Status))
    {
        /* Not all elements may have been converted */
        *ElementCount = LocalElementCount;
    }

    /* Free the local (unpacked) buffer and return status */
    BlMmFreeHeap(LocalElements);
    return Status;
}
Example #25
0
NTSTATUS
BlHtCreate (
    _In_ ULONG Size,
    _In_ PBL_HASH_TABLE_HASH_FUNCTION HashFunction,
    _In_ PBL_HASH_TABLE_COMPARE_FUNCTION CompareFunction,
    _Out_ PULONG Id
    )
{
    NTSTATUS Status;
    PBL_HASH_TABLE HashTable;
    ULONG i;

    /* Assume failure */
    HashTable = NULL;

    /* Can't create a table with no ID */
    if (!Id)
    {
        return STATUS_INVALID_PARAMETER;
    }

    /* Check if we don't already have a hash table table */
    if (!HtTableSize)
    {
        /* Allocate it and zero it out */
        HtTableSize = 4;
        HtTableArray = BlMmAllocateHeap(HtTableSize * sizeof(PVOID));
        if (!HtTableArray)
        {
            Status = STATUS_NO_MEMORY;
            goto Quickie;
        }
        RtlZeroMemory(HtTableArray, HtTableSize * sizeof(PVOID));
        HtTableEntries = 0;
    }

    /* Allocate the hash table */
    HashTable = BlMmAllocateHeap(sizeof(*HashTable));
    if (!HashTable)
    {
        Status = STATUS_NO_MEMORY;
        goto Quickie;
    }

    /* Fill it out */
    HashTable->HashFunction = HashFunction ? HashFunction : DefaultHashFunction;
    HashTable->CompareFunction = CompareFunction ? CompareFunction : HtpCompareKeys;
    HashTable->Size = Size ? Size : 13;

    /* Allocate the hash links, one for each bucket */
    HashTable->HashLinks = BlMmAllocateHeap(sizeof(LIST_ENTRY) * HashTable->Size);
    if (!HashTable->HashLinks)
    {
        Status = STATUS_NO_MEMORY;
        goto Quickie;
    }

    /* Initialize the hash links */
    for (i = 0; i < HashTable->Size; i++)
    {
        InitializeListHead(&HashTable->HashLinks[i]);
    }

    /* Save us in the table of hash tables */
    Status = BlTblSetEntry((PVOID**)&HtTableArray,
                           &Size,
                           HashTable,
                           Id,
                           TblDoNotPurgeEntry);
    if (NT_SUCCESS(Status))
    {
        /* One more -- we're done */
        ++HtTableEntries;
        return Status;
    }

Quickie:
    /* Check if we just allocated the table array now */
    if (!(HtTableEntries) && (HtTableArray))
    {
        /* Free it */
        BlMmFreeHeap(HtTableArray);
        HtTableArray = NULL;
        HtTableSize = 0;
    }

    /* Check if we allocated a hash table*/
    if (HashTable)
    {
        /* With links? */
        if (HashTable->HashLinks)
        {
            /* Free them */
            BlMmFreeHeap(HashTable->HashLinks);
        }

        /* Free the table*/
        BlMmFreeHeap(HashTable);
    }

    /* We're done */
    return Status;
}
Example #26
0
NTSTATUS
BiOpenKey(
    _In_ HANDLE ParentHandle,
    _In_ PWCHAR KeyName,
    _Out_ PHANDLE Handle
    )
{
    PBI_KEY_OBJECT ParentKey, NewKey;
    PBI_KEY_HIVE ParentHive;
    NTSTATUS Status;
    ULONG NameLength, SubNameLength, NameBytes;
    PWCHAR NameStart, NameBuffer;
    UNICODE_STRING KeyString;
    HCELL_INDEX KeyCell;
    PHHIVE Hive;
    PCM_KEY_NODE ParentNode;

    /* Convert from a handle to our key object */
    ParentKey = (PBI_KEY_OBJECT)ParentHandle;

    /* Extract the hive and node information */
    ParentHive = ParentKey->KeyHive;
    ParentNode = ParentKey->KeyNode;
    Hive = &ParentKey->KeyHive->Hive.Hive;

    /* Initialize variables */
    KeyCell = HCELL_NIL;
    Status = STATUS_SUCCESS;
    NameBuffer = NULL;

    /* Loop as long as there's still portions of the key name in play */
    NameLength = wcslen(KeyName);
    while (NameLength)
    {
        /* Find the first path separator */
        NameStart = wcschr(KeyName, OBJ_NAME_PATH_SEPARATOR);
        if (NameStart)
        {
            /* Look only at the key before the separator */
            SubNameLength = NameStart - KeyName;
            ++NameStart;
        }
        else
        {
            /* No path separator, this is the final leaf key */
            SubNameLength = NameLength;
        }

        /* Free the name buffer from the previous pass if needed */
        if (NameBuffer)
        {
            BlMmFreeHeap(NameBuffer);
        }

        /* Allocate a buffer to hold the name of this specific subkey only */
        NameBytes = SubNameLength * sizeof(WCHAR);
        NameBuffer = BlMmAllocateHeap(NameBytes + sizeof(UNICODE_NULL));
        if (!NameBuffer)
        {
            Status = STATUS_NO_MEMORY;
            goto Quickie;
        }

        /* Copy and null-terminate the name of the subkey */
        RtlCopyMemory(NameBuffer, KeyName, NameBytes);
        NameBuffer[SubNameLength] = UNICODE_NULL;

        /* Convert it into a UNICODE_STRING and try to find it */
        RtlInitUnicodeString(&KeyString, NameBuffer);
        KeyCell = CmpFindSubKeyByName(Hive, ParentNode, &KeyString);
        if (KeyCell == HCELL_NIL)
        {
            Status = STATUS_OBJECT_NAME_NOT_FOUND;
            goto Quickie;
        }

        /* We found it -- get the key node out of it */
        ParentNode = (PCM_KEY_NODE)HvGetCell(Hive, KeyCell);
        if (!ParentNode)
        {
            Status = STATUS_REGISTRY_CORRUPT;
            goto Quickie;
        }

        /* Update the key name to the next remaining path element */
        KeyName = NameStart;
        if (NameStart)
        {
            /* Update the length to the remainder of the path */
            NameLength += -1 - SubNameLength;
        }
        else
        {
            /* There's nothing left, this was the leaf key */
            NameLength = 0;
        }
    }

    /* Allocate a key object */
    NewKey = BlMmAllocateHeap(sizeof(*NewKey));
    if (!NewKey)
    {
        /* Bail out if we had no memory for it */
        Status = STATUS_NO_MEMORY;
        goto Quickie;
    }

    /* Fill out the key object data */
    NewKey->KeyNode = ParentNode;
    NewKey->KeyHive = ParentHive;
    NewKey->KeyName = NameBuffer;
    NewKey->KeyCell = KeyCell;

    /* Add a reference to the hive */
    ++ParentHive->ReferenceCount;

    /* Return the object back to the caller */
    *Handle = NewKey;

Quickie:
    /* If we had a name buffer, free it */
    if (NameBuffer)
    {
        BlMmFreeHeap(NameBuffer);
    }

    /* Return status of the open operation */
    return Status;
}
Example #27
0
NTSTATUS
BlAppendBootOptions (
    _In_ PBL_LOADED_APPLICATION_ENTRY AppEntry,
    _In_ PBL_BCD_OPTION Options
    )
{
    ULONG OptionsSize, CurrentSize;
    PBL_BCD_OPTION NewOptions, CurrentOptions, NextOption;
    NTSTATUS Status;
    ULONG CurrentOffset;

    /* Get the current options */
    CurrentOptions = AppEntry->BcdData;

    /* Calculate the size of the current, and the appended options */
    CurrentSize = BlGetBootOptionListSize(CurrentOptions);
    OptionsSize = BlGetBootOptionListSize(Options);

    /* Allocate a buffer for the concatenated (new) options */
    NewOptions = BlMmAllocateHeap(CurrentSize + OptionsSize);
    if (!NewOptions)
    {
        return STATUS_NO_MEMORY;
    }

    /* Copy the old options, and the ones to be added */
    RtlCopyMemory(NewOptions, CurrentOptions, CurrentSize);
    RtlCopyMemory(&NewOptions[OptionsSize], Options, OptionsSize);

    /* We made it! */
    Status = STATUS_SUCCESS;

    /* Scan through to the last option in the list */
    CurrentOffset = 0;
    do
    {
        NextOption = (PBL_BCD_OPTION)((ULONG_PTR)NewOptions + CurrentOffset);
        CurrentOffset = NextOption->NextEntryOffset;
    } while (CurrentOffset);

    /* Every other option now has to have its offset adjusted */
    do
    {
        NextOption->NextEntryOffset += OptionsSize;
        NextOption = (PBL_BCD_OPTION)((ULONG_PTR)NewOptions + NextOption->NextEntryOffset);
    } while (NextOption->NextEntryOffset);

    /* If we already had internal options, free them */
    if (AppEntry->Flags & BL_APPLICATION_ENTRY_BCD_OPTIONS_INTERNAL)
    {
        BlMmFreeHeap(AppEntry->BcdData);
    }

    /* Write the new pointer */
    AppEntry->BcdData = NewOptions;

    /* Options are now internal, not external */
    AppEntry->Flags &= ~BL_APPLICATION_ENTRY_BCD_OPTIONS_EXTERNAL;
    AppEntry->Flags |= BL_APPLICATION_ENTRY_BCD_OPTIONS_INTERNAL;
    return Status;
}
Example #28
0
NTSTATUS
BlGetBootOptionDevice (
    _In_ PBL_BCD_OPTION List,
    _In_ ULONG Type,
    _Out_ PBL_DEVICE_DESCRIPTOR* Value,
    _In_opt_ PBL_BCD_OPTION* ExtraOptions
    )
{
    NTSTATUS Status;
    PBL_BCD_OPTION Option, ListData, ListCopy, SecureListData;
    PBCD_DEVICE_OPTION BcdDevice;
    ULONG DeviceSize, ListOffset, ListSize;
    PBL_DEVICE_DESCRIPTOR DeviceDescriptor, SecureDescriptor;
    //PGUID AppIdentifier;
    BcdElementType ElementType;

    /* Make sure this is a BCD_TYPE_DEVICE */
    ElementType.PackedValue = Type;
    if (ElementType.Format != BCD_TYPE_DEVICE)
    {
        return STATUS_INVALID_PARAMETER;
    }

    /* Return the data */
    Option = MiscGetBootOption(List, Type);
    if (!Option)
    {
        /* Set failure if no data exists */
        Status = STATUS_NOT_FOUND;
    }
    else
    {
        /* Otherwise, read the size of the BCD device encoded */
        BcdDevice = (PBCD_DEVICE_OPTION)((ULONG_PTR)Option + Option->DataOffset);
        DeviceSize = BcdDevice->DeviceDescriptor.Size;

        /* Allocate a buffer to copy it into */
        DeviceDescriptor = BlMmAllocateHeap(DeviceSize);
        if (!DeviceDescriptor)
        {
            return STATUS_NO_MEMORY;
        }

        /* Copy it into that buffer */
        RtlCopyMemory(DeviceDescriptor, &BcdDevice->DeviceDescriptor, DeviceSize);
        Status = STATUS_SUCCESS;
    }

    /* Check if extra options were requested */
    if (ExtraOptions)
    {
        /* See where they are */
        ListOffset = Option->ListOffset;
        if (ListOffset)
        {
            /* See how big they are */
            ListData = (PBL_BCD_OPTION)((ULONG_PTR)Option + ListOffset);
            ListSize = BlGetBootOptionListSize(ListData);

            /* Allocate a buffer to hold them into */
            ListCopy = BlMmAllocateHeap(ListSize);
            if (!ListCopy)
            {
                Status = STATUS_NO_MEMORY;
                goto Quickie;
            }

            /* Copy them in there */
            RtlCopyMemory(ListCopy, ListData, ListSize);
        }
    }

#ifdef _SECURE_BOOT_
    /* Filter out SecureBoot Options */
    AppIdentifier = BlGetApplicationIdentifier();
    if (BlpBootOptionCallbacks)
    {
        DeviceCallback = BlpBootOptionCallbacks->Device;
        if (DeviceCallback)
        {
            Status = DeviceCallback(BlpBootOptionCallbackCookie,
                                    Status,
                                    0,
                                    AppIdentifier,
                                    Type,
                                    &SecureDescriptor,
                                    PtrOptionData);
        }
    }
#else
    /* No secure boot, so the secure descriptors are the standard ones */
    SecureDescriptor = DeviceDescriptor;
    SecureListData = ListCopy;
#endif

    /* Check if the data was read correctly */
    if (NT_SUCCESS(Status))
    {
        /* Check if we had a new descriptor after filtering */
        if (SecureDescriptor != DeviceDescriptor)
        {
            /* Yep -- if we had an old one, free it */
            if (DeviceDescriptor)
            {
                BlMmFreeHeap(DeviceDescriptor);
            }
        }

        /* Check if we had a new list after filtering */
        if (SecureListData != ListCopy)
        {
            /* Yep -- if we had an old list, free it */
            if (ListCopy)
            {
                BlMmFreeHeap(ListCopy);
            }
        }

        /* Finally, check if the caller wanted extra options */
        if (ExtraOptions)
        {
            /* Yep -- so pass the caller our copy */
            *ExtraOptions = ListCopy;
            ListCopy = NULL;
        }

        /* Caller always wants data back, so pass them our copy */
        *Value = DeviceDescriptor;
        DeviceDescriptor = NULL;
    }

Quickie:
    /* On the failure path, if these buffers are active, we should free them */
    if (ListCopy)
    {
        BlMmFreeHeap(ListCopy);
    }
    if (DeviceDescriptor)
    {
        BlMmFreeHeap(DeviceDescriptor);
    }

    /* All done */
    return Status;
}