Example #1
0
NTSTATUS
FileTableDestroyEntry (
    _In_ PBL_FILE_ENTRY FileEntry, 
    _In_ ULONG Index
    )
{
    ULONG DeviceId;
    PBL_DEVICE_ENTRY DeviceEntry;
    NTSTATUS Status;

    DeviceId = FileEntry->DeviceId;
    if (DmTableEntries > DeviceId)
    {
        DeviceEntry = DmDeviceTable[DeviceId];
        if (DeviceEntry)
        {
            --DeviceEntry->ReferenceCount;
        }
    }

    Status = FileEntry->Callbacks.Close(FileEntry);

    BlMmFreeHeap(FileEntry);

    FileTable[Index] = NULL;
    return Status;
}
Example #2
0
VOID
BiCloseKey (
    _In_ HANDLE KeyHandle
    )
{
    PBI_KEY_HIVE KeyHive;
    PBI_KEY_OBJECT KeyObject;

    /* Get the key object and hive */
    KeyObject = (PBI_KEY_OBJECT)KeyHandle;
    KeyHive = KeyObject->KeyHive;

    /* Check if we have a hive, or name, or key node */
    if ((KeyHive) || (KeyObject->KeyNode) || (KeyObject->KeyName))
    {
        /* Drop a reference, see if it's the last one */
        BiDereferenceHive(KeyHandle);
        if (!KeyHive->ReferenceCount)
        {
            /* Check if we should flush it */
            if (KeyHive->Flags & BI_FLUSH_HIVE)
            {
                BiFlushHive(KeyHandle);
            }

            /* Unmap the hive */
            //MmPapFreePages(KeyHive->ImageBase, 1);
            EfiPrintf(L"Leaking hive memory\r\n");

            /* Free the hive and hive path */
            BlMmFreeHeap(KeyHive->FilePath);
            BlMmFreeHeap(KeyHive);
        }

        /* Check if a key name is present */
        if (KeyObject->KeyName)
        {
            /* Free it */
            BlMmFreeHeap(KeyObject->KeyName);
        }
    }

    /* Free the object */
    BlMmFreeHeap(KeyObject);
}
Example #3
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 #4
0
VOID
NTAPI
RtlpFreeMemory (
    _In_ PVOID Mem,
    _In_ ULONG Tag
    )
{
    UNREFERENCED_PARAMETER(Tag);
    BlMmFreeHeap(Mem);
}
Example #5
0
NTSTATUS
BlHtDelete (
    _In_ ULONG TableId,
    _In_ PBL_HASH_ENTRY Entry
    )
{
    PBL_HASH_TABLE HashTable;
    ULONG HashValue;
    NTSTATUS Status;
    PLIST_ENTRY HashLinkHead, HashLink;
    PBL_HASH_NODE HashNode;

    /* Check if the table ID is invalid, or we have no entry, or it's malformed */
    if ((HtTableSize <= TableId) ||
        !(Entry) ||
        !(Entry->Size) ||
        !(Entry->Value) ||
        ((Entry->Flags & BL_HT_VALUE_IS_INLINE) && (Entry->Size != sizeof(ULONG))))
    {
        /* Fail */
        Status = STATUS_INVALID_PARAMETER;
    }
    else
    {
        /* Otherwise, get the hash table for this index */
        HashTable = HtTableArray[TableId];

        /* Get the hash bucket */
        HashValue = HashTable->HashFunction(Entry, HashTable->Size);

        /* Start iterating each entry in the bucket, assuming failure */
        Status = STATUS_NOT_FOUND;
        HashLinkHead = &HashTable->HashLinks[HashValue];
        HashLink = HashLinkHead->Flink;
        while (HashLink != HashLinkHead)
        {
            /* Get a node in this bucket, and compare the value */
            HashNode = CONTAINING_RECORD(HashLink, BL_HASH_NODE, ListEntry);
            if (HashTable->CompareFunction(&HashNode->Entry, Entry))
            {
                /* Remove it from the list and free it */
                RemoveEntryList(&HashNode->ListEntry);
                BlMmFreeHeap(HashNode);
                return STATUS_SUCCESS;
            }

            /* Try the next node */
            HashLink = HashLink->Flink;
        }
    }

    /* Return back to the caller */
    return Status;
}
Example #6
0
VOID
NTAPI
CmpFree (
    _In_ PVOID Ptr,
    _In_ ULONG Quota
    )
{
    UNREFERENCED_PARAMETER(Quota);

    /* Call the heap allocator */
    BlMmFreeHeap(Ptr);
}
Example #7
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 #8
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 #9
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 #10
0
NTSTATUS
MmBapFreeBlockAllocatorTableEntry (
    _In_ PVOID Entry,
    _In_ ULONG Index
    )
{
    PBL_BLOCK_DESCRIPTOR BlockInfo = (PBL_BLOCK_DESCRIPTOR)Entry;
    NTSTATUS Status, LocalStatus;

    /* Assume success */
    Status = STATUS_SUCCESS;

    /* Check if there was at least one reference */
    if (BlockInfo->ReferenceCount > 1)
    {
        /* Try to delete the allocator */
        LocalStatus = BlpMmDeleteBlockAllocator(BlockInfo->BlockId);
        if (!NT_SUCCESS(LocalStatus))
        {
            /* Remember status on failure only */
            Status = LocalStatus;
        }
    }

    /* Now destroy the allocator's descriptor */
    LocalStatus = BlMmFreeHeap(BlockInfo);
    if (!NT_SUCCESS(LocalStatus))
    {
        /* Remember status on failure only */
        Status = LocalStatus;
    }

    /* Free the entry, and return failure, if any */
    MmBlockAllocatorTable[Index] = NULL;
    return Status;
}
Example #11
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 #12
0
NTSTATUS
BlpResourceInitialize (
    VOID
    )
{
    NTSTATUS Status;
    PIMAGE_SECTION_HEADER ResourceSection;
    PVOID ImageBase;
    ULONG ImageSize, VRes, HRes;
    BOOLEAN UsePrimary;

    /* Default to using fallback */
    UsePrimary = FALSE;

    /* Initialize all globals */
    ResMuiImageBase = 0;
    ResMuiImageSize = 0;
    ResRootDirectoryPrimary = 0;
    ResRootDirectoryPrimaryOffset = 0;
    ResPeImageBasePrimary = 0;
    ResPeImageEndPrimary = 0;
    ResRootDirectoryFallback = 0;
    ResRootDirectoryFallbackOffset = 0;
    ResPeImageBaseFallback = 0;
    ResPeImageEndFallback = 0;
    ResRootDirectory = 0;
    ResRootDirectoryOffset = 0;
    ResPeImageBase = 0;
    ResPeImageEnd = 0;
    ResLoadedFontFiles = 0;

    /* Check if we had allocated a locale already */
    if (ResLocale)
    {
        /* Free it and reset */
        BlMmFreeHeap(ResLocale);
        ResLocale = 0;
    }

    /* Get our base address and size*/
    Status = BlGetApplicationBaseAndSize(&ImageBase, &ImageSize);
    if (!NT_SUCCESS(Status))
    {
        return Status;
    }

    /* Find our resource section */
    ResourceSection = BlImgFindSection(ImageBase, ImageSize);
    if (ResourceSection)
    {
        /* The resource section will be our fallback. Save down its details */
        ResRootDirectoryFallbackOffset = ResourceSection->VirtualAddress;
        ResPeImageBaseFallback = ImageBase;
        ResPeImageEndFallback = (PVOID)((ULONG_PTR)ImageBase + ImageSize);
        ResRootDirectoryFallback = (PIMAGE_RESOURCE_DIRECTORY)((ULONG_PTR)ImageBase +
                                            ResRootDirectoryFallbackOffset);
    }

    /* Get the current screen resolution and check if we're in graphics mode */
    Status = BlDisplayGetScreenResolution(&HRes, &VRes);
    if ((NT_SUCCESS(Status)) && ((HRes != 640) || (VRes != 200)))
    {
        /* We are... we should load MUI data */
        Status = STATUS_NOT_IMPLEMENTED;//ResInitializeMuiResources();
        if (NT_SUCCESS(Status))
        {
            /* And not rely on the fallback */
            UsePrimary = TRUE;
        }
    }

    /* Load the locale resources */
    return ResSelectLocale(UsePrimary);
}
Example #13
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 #14
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 #15
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 #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
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 #18
0
NTSTATUS
FileIoOpen (
    _In_ ULONG DeviceId,
    _In_ PWCHAR FileName,
    _In_ ULONG Flags,
    _In_ ULONG Unknown,
    _In_ PBL_TBL_LOOKUP_ROUTINE CompareRoutine,
    _Out_opt_ PBL_FILE_ENTRY *NewFileEntry
    )
{
    PWCHAR FileNameCopy, ParentFileName;
    NTSTATUS Status;
    PBL_DEVICE_ENTRY DeviceEntry;
    PBL_FILE_SYSTEM_ENTRY FileSystem;
    ULONG FileId, CheckFlags;
    PBL_FILE_ENTRY DirectoryEntry, FileEntry;
    PLIST_ENTRY NextEntry, ListHead;

    /* Preinitialize variables for failure */
    DirectoryEntry = NULL;
    FileNameCopy = NULL;
    ParentFileName = NULL;
    Status = STATUS_SUCCESS;

    /* Bail out if the device ID is invalid */
    if (DmTableEntries <= DeviceId)
    {
        return STATUS_ACCESS_DENIED;
    }

    /* Bail out if there's no device entry */
    DeviceEntry = DmDeviceTable[DeviceId];
    if (!DeviceEntry)
    {
        return STATUS_ACCESS_DENIED;
    }

    /* Read access is always required for touching the device */
    CheckFlags = Flags | BL_FILE_READ_ACCESS;

    /* Check if the device is granting us read access */
    if ((CheckFlags & BL_FILE_READ_ACCESS) &&
        (!(DeviceEntry->Flags & BL_DEVICE_ENTRY_OPENED) ||
         !(DeviceEntry->Flags & BL_DEVICE_ENTRY_READ_ACCESS)))
    {
        EfiPrintf(L"Access denied\r\n");
        return STATUS_ACCESS_DENIED;
    }

    /* Check if the device is granting us write access */
    if ((CheckFlags & BL_FILE_WRITE_ACCESS) &&
        (!(DeviceEntry->Flags & BL_DEVICE_ENTRY_OPENED) ||
         !(DeviceEntry->Flags & BL_DEVICE_ENTRY_WRITE_ACCESS)))
    {
        EfiPrintf(L"Access denied2\r\n");
        return STATUS_ACCESS_DENIED;
    }

    /* Check if we already have this file open */
    FileEntry = (PBL_FILE_ENTRY )BlTblFindEntry(FileTable,
                                                FileEntries,
                                                &FileId,
                                                CompareRoutine,
                                                &DeviceId,
                                                FileName,
                                                &Flags,
                                                &Unknown);
    if (FileEntry)
    {
        EfiPrintf(L"Entry exists: %p\n", FileEntry);
        goto FileOpened;
    }

    /* Check if we are opening the root drive or an actual file/directory */
    if ((*FileName != OBJ_NAME_PATH_SEPARATOR) || (FileName[1]))
    {
        /* Get the name of the directory */
        ParentFileName = FileIoCopyParentDirectoryPath(FileName);
        if (!ParentFileName)
        {
            Status = STATUS_NO_MEMORY;
            goto Quickie;
        }

        /* Open it */
        Status = FileIoOpen(DeviceId,
                            ParentFileName,
                            BL_FILE_READ_ACCESS | BL_DIRECTORY_ACCESS,
                            Unknown,
                            FileTableCompareWithSubsetAttributes,
                            &DirectoryEntry);
        if (!NT_SUCCESS(Status))
        {
            goto Quickie;
        }

        /* Now get the the file name itself */
        FileNameCopy = FileIoCopyFileName(FileName);
        if (!FileNameCopy)
        {
            Status = STATUS_NO_MEMORY;
            goto Quickie;
        }

        /* Open it */
        Status = DirectoryEntry->Callbacks.Open(DirectoryEntry,
                                                FileNameCopy,
                                                Flags,
                                                &FileEntry);
    }
    else
    {
        /* We're opening the root, scan through all the file systems */
        Status = STATUS_UNSUCCESSFUL;
        ListHead = &RegisteredFileSystems;
        NextEntry = ListHead->Flink;
        while (NextEntry != ListHead)
        {
            /* Try to mount this one */
            FileSystem = CONTAINING_RECORD(NextEntry, BL_FILE_SYSTEM_ENTRY, ListEntry);
            Status = FileSystem->MountCallback(DeviceId, Unknown, &FileEntry);
            if (NT_SUCCESS(Status))
            {
                /* Mount successful */
                break;
            }

            /* Try the next file system */
            NextEntry = NextEntry->Flink;
        }

        /* Nothing to free on this path */
        FileNameCopy = NULL;
    }

    /* Handle failure */
    if (!NT_SUCCESS(Status))
    {
        EfiPrintf(L"Could not open file!: %lx\r\n", Status);
        goto Quickie;
    }

    /* Save the unknown */
    FileEntry->Unknown = Unknown;

    /* Convert open flags into entry flags */
    if (Flags & BL_FILE_READ_ACCESS)
    {
        FileEntry->Flags |= BL_FILE_ENTRY_READ_ACCESS;
    }
    if (Flags & BL_FILE_WRITE_ACCESS)
    {
        FileEntry->Flags |= BL_FILE_ENTRY_WRITE_ACCESS;
    }

    /* Save the file into the file table */
    Status = BlTblSetEntry(&FileTable,
                           &FileEntries,
                           (PVOID)FileEntry,
                           &FileId,
                           FileTablePurgeEntry);
    if (!NT_SUCCESS(Status))
    {
        /* Close it if that failed */
        FileEntry->Callbacks.Close(FileEntry);
        goto Quickie;
    }

    /* Add a reference on the device, and save our file ID  */
    ++DeviceEntry->ReferenceCount;
    Status = STATUS_SUCCESS;
    FileEntry->FileId = FileId;

    EfiPrintf(L"File %s opened with ID: %lx\r\n", FileEntry->FilePath, FileId);

FileOpened:
    /* Add a reference to the file entry, and see if this is the first one */
    if (++FileEntry->ReferenceCount == 1)
    {
        /* Reset unknowns */
        FileEntry->TotalBytesRead = 0;
        FileEntry->Unknown2 = 0;
    }

    /* Set the file as opened */
    FileEntry->Flags |= BL_FILE_ENTRY_OPENED;

    /* Not sure what this flag does */
    if (Flags & BL_UNKNOWN_ACCESS)
    {
        FileEntry->Flags |= BL_FILE_ENTRY_UNKNOWN_ACCESS;
    }

    /* If the caller wanted the entry back, return it */
    if (NewFileEntry)
    {
        *NewFileEntry = FileEntry;
    }

Quickie:
    /* Close the parent */
    if (DirectoryEntry)
    {
        BlFileClose(DirectoryEntry->FileId);
    }

    /* Free the parent name copy */
    if (ParentFileName)
    {
        BlMmFreeHeap(ParentFileName);
    }

    /* Free the file name copy */
    if (FileNameCopy)
    {
        BlMmFreeHeap(FileNameCopy);
    }

    /* Return back to caller */
    return Status;
}
Example #19
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;
}
Example #20
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 #21
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 #22
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 #23
0
NTSTATUS
BiGetObjectDescription (
    _In_ HANDLE ObjectHandle,
    _Out_ PBCD_OBJECT_DESCRIPTION Description
    )
{
    NTSTATUS Status;
    HANDLE DescriptionHandle;
    PULONG Data;
    ULONG Length;

    /* Initialize locals */
    Data = NULL;
    DescriptionHandle = NULL;

    /* Open the description key */
    Status = BiOpenKey(ObjectHandle, L"Description", &DescriptionHandle);
    if (NT_SUCCESS(Status))
    {
        /* It exists */
        Description->Valid = TRUE;

        /* Read the type */
        Length = 0;
        Status = BiGetRegistryValue(DescriptionHandle,
                                    L"Type", 
                                    REG_DWORD,
                                    (PVOID*)&Data,
                                    &Length);
        if (NT_SUCCESS(Status))
        {
            /* Make sure it's the length we expected it to be */
            if (Length == sizeof(Data))
            {
                /* Return the type that is stored there */
                Description->Type = *Data;
            }
            else
            {
                /* Invalid type value */
                Status = STATUS_OBJECT_TYPE_MISMATCH;
            }
        }
    }

    /* Did we have a handle open? */
    if (DescriptionHandle)
    {
        /* Close it */
        BiCloseKey(DescriptionHandle);
    }

    /* Did we have data allocated? */
    if (Data)
    {
        /* Free it */
        BlMmFreeHeap(Data);
    }

    /* Return back to caller */
    return Status;
}