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; }
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); }
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; }
VOID NTAPI RtlpFreeMemory ( _In_ PVOID Mem, _In_ ULONG Tag ) { UNREFERENCED_PARAMETER(Tag); BlMmFreeHeap(Mem); }
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; }
VOID NTAPI CmpFree ( _In_ PVOID Ptr, _In_ ULONG Quota ) { UNREFERENCED_PARAMETER(Quota); /* Call the heap allocator */ BlMmFreeHeap(Ptr); }
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; }
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; }
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; }
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; }
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; }
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); }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }