1 /* 2 * COPYRIGHT: See COPYING.ARM in the top level directory 3 * PROJECT: ReactOS UEFI Boot Library 4 * FILE: boot/environ/lib/mm/blkalloc.c 5 * PURPOSE: Boot Library Memory Manager Block Allocator 6 * PROGRAMMER: Alex Ionescu (alex.ionescu@reactos.org) 7 */ 8 9 /* INCLUDES ******************************************************************/ 10 11 #include "bl.h" 12 13 /* DATA VARIABLES ************************************************************/ 14 15 PVOID* MmBlockAllocatorTable; 16 ULONG MmBlockAllocatorTableEntries; 17 BOOLEAN MmBlockAllocatorInitialized; 18 19 typedef struct _BL_BLOCK_DESCRIPTOR 20 { 21 LIST_ENTRY ListHead; 22 ULONG Unknown; 23 BL_MEMORY_TYPE Type; 24 ULONG Attributes; 25 ULONG Unknown2; 26 ULONG Count; 27 ULONG Count2; 28 ULONG Size; 29 ULONG BlockId; 30 ULONG ReferenceCount; 31 } BL_BLOCK_DESCRIPTOR, *PBL_BLOCK_DESCRIPTOR; 32 33 typedef struct _BL_BLOCK_ENTRY 34 { 35 LIST_ENTRY ListEntry; 36 ULONG Todo; 37 } BL_BLOCK_ENTRY, *PBL_BLOCK_ENTRY; 38 39 /* FUNCTIONS *****************************************************************/ 40 41 BOOLEAN 42 MmBapCompareBlockAllocatorTableEntry ( 43 _In_ PVOID Entry, 44 _In_ PVOID Argument1, 45 _In_ PVOID Argument2, 46 _In_ PVOID Argument3, 47 _In_ PVOID Argument4 48 ) 49 { 50 PBL_BLOCK_DESCRIPTOR BlockInfo = (PBL_BLOCK_DESCRIPTOR)Entry; 51 ULONG BlockId = PtrToUlong(Argument1); 52 53 /* Check if the block ID matches */ 54 return BlockInfo->BlockId == BlockId; 55 } 56 57 PBL_BLOCK_DESCRIPTOR 58 MmBapFindBlockInformation ( 59 ULONG BlockId 60 ) 61 { 62 ULONG EntryId; 63 64 /* Find the block that matches */ 65 EntryId = BlockId; 66 return BlTblFindEntry(MmBlockAllocatorTable, 67 MmBlockAllocatorTableEntries, 68 &EntryId, 69 MmBapCompareBlockAllocatorTableEntry, 70 UlongToPtr(EntryId), 71 NULL, 72 NULL, 73 NULL); 74 } 75 76 NTSTATUS 77 MmBapFreeBlockAllocatorDescriptor ( 78 _In_ PBL_BLOCK_DESCRIPTOR BlockInfo, 79 _In_ PBL_BLOCK_ENTRY BlockEntry 80 ) 81 { 82 /* @TODO FIXME: Later */ 83 EfiPrintf(L"Block free not yet implemented\r\n"); 84 return STATUS_NOT_IMPLEMENTED; 85 } 86 87 NTSTATUS 88 BlpMmDeleteBlockAllocator ( 89 _In_ ULONG BlockId 90 ) 91 { 92 NTSTATUS Status, LocalStatus; 93 PBL_BLOCK_DESCRIPTOR BlockInfo; 94 PLIST_ENTRY ListHead, NextEntry; 95 PBL_BLOCK_ENTRY BlockEntry; 96 97 /* Nothing to delete if we're not initialized */ 98 if (!MmBlockAllocatorInitialized) 99 { 100 return STATUS_UNSUCCESSFUL; 101 } 102 103 /* Find the block descriptor */ 104 BlockInfo = MmBapFindBlockInformation(BlockId); 105 if (BlockInfo) 106 { 107 /* Assume success for now */ 108 Status = STATUS_SUCCESS; 109 110 /* Do we have at least one reference? */ 111 if (BlockInfo->ReferenceCount) 112 { 113 /* Iterate over the allocated blocks */ 114 ListHead = &BlockInfo->ListHead; 115 NextEntry = ListHead->Flink; 116 while (NextEntry != ListHead) 117 { 118 /* Free each one */ 119 BlockEntry = CONTAINING_RECORD(NextEntry, 120 BL_BLOCK_ENTRY, 121 ListEntry); 122 LocalStatus = MmBapFreeBlockAllocatorDescriptor(BlockInfo, 123 BlockEntry); 124 if (!NT_SUCCESS(LocalStatus)) 125 { 126 /* Remember status on failure only */ 127 Status = LocalStatus; 128 } 129 } 130 131 /* Drop a reference */ 132 BlockInfo->ReferenceCount--; 133 } 134 else 135 { 136 /* There aren't any references, so why are we being called? */ 137 Status = STATUS_INVALID_PARAMETER; 138 } 139 } 140 else 141 { 142 /* No block exists with this ID */ 143 Status = STATUS_UNSUCCESSFUL; 144 } 145 146 /* Return back */ 147 return Status; 148 } 149 150 NTSTATUS 151 MmBapFreeBlockAllocatorTableEntry ( 152 _In_ PVOID Entry, 153 _In_ ULONG Index 154 ) 155 { 156 PBL_BLOCK_DESCRIPTOR BlockInfo = (PBL_BLOCK_DESCRIPTOR)Entry; 157 NTSTATUS Status, LocalStatus; 158 159 /* Assume success */ 160 Status = STATUS_SUCCESS; 161 162 /* Check if there was at least one reference */ 163 if (BlockInfo->ReferenceCount > 1) 164 { 165 /* Try to delete the allocator */ 166 LocalStatus = BlpMmDeleteBlockAllocator(BlockInfo->BlockId); 167 if (!NT_SUCCESS(LocalStatus)) 168 { 169 /* Remember status on failure only */ 170 Status = LocalStatus; 171 } 172 } 173 174 /* Now destroy the allocator's descriptor */ 175 LocalStatus = BlMmFreeHeap(BlockInfo); 176 if (!NT_SUCCESS(LocalStatus)) 177 { 178 /* Remember status on failure only */ 179 Status = LocalStatus; 180 } 181 182 /* Free the entry, and return failure, if any */ 183 MmBlockAllocatorTable[Index] = NULL; 184 return Status; 185 } 186 187 NTSTATUS 188 MmBapPurgeBlockAllocatorTableEntry ( 189 _In_ PVOID Entry 190 ) 191 { 192 PBL_BLOCK_DESCRIPTOR BlockInfo = (PBL_BLOCK_DESCRIPTOR)Entry; 193 NTSTATUS Status; 194 195 /* Check if there's a reference on the block descriptor */ 196 if (BlockInfo->ReferenceCount) 197 { 198 /* Don't allow purging */ 199 Status = STATUS_UNSUCCESSFUL; 200 } 201 else 202 { 203 /* Free the entry */ 204 Status = MmBapFreeBlockAllocatorTableEntry(BlockInfo, 205 BlockInfo->BlockId); 206 } 207 208 /* Return purge status */ 209 return Status; 210 } 211 212 NTSTATUS 213 BlpMmCreateBlockAllocator ( 214 VOID 215 ) 216 { 217 PBL_BLOCK_DESCRIPTOR BlockInfo; 218 ULONG BlockId; 219 NTSTATUS Status; 220 221 /* If the block allocator isn't initialized, bail out */ 222 BlockId = -1; 223 if (!MmBlockAllocatorInitialized) 224 { 225 goto Quickie; 226 } 227 228 /* Allocate a block descriptor and zero it out */ 229 BlockInfo = BlMmAllocateHeap(sizeof(*BlockInfo)); 230 if (!BlockInfo) 231 { 232 goto Quickie; 233 } 234 RtlZeroMemory(BlockInfo, sizeof(*BlockInfo)); 235 236 /* Setup the block descriptor */ 237 BlockInfo->Attributes = 0; 238 BlockInfo->Type = BlLoaderBlockMemory; 239 BlockInfo->Unknown = 1; 240 BlockInfo->Unknown2 = 1; 241 BlockInfo->Size = PAGE_SIZE; 242 BlockInfo->Count = 128; 243 BlockInfo->Count2 = 128; 244 InitializeListHead(&BlockInfo->ListHead); 245 246 /* Add it to the list of block descriptors */ 247 Status = BlTblSetEntry(&MmBlockAllocatorTable, 248 &MmBlockAllocatorTableEntries, 249 BlockInfo, 250 &BlockId, 251 MmBapPurgeBlockAllocatorTableEntry); 252 if (NT_SUCCESS(Status)) 253 { 254 /* Add the initial reference and store the block ID */ 255 BlockInfo->ReferenceCount = 1; 256 BlockInfo->BlockId = BlockId; 257 } 258 259 Quickie: 260 /* On failure, free the block descriptor */ 261 if (BlockId == -1) 262 { 263 BlMmFreeHeap(BlockInfo); 264 } 265 266 /* Return the block descriptor ID, or -1 on failure */ 267 return BlockId; 268 } 269 270 NTSTATUS 271 MmBaInitialize ( 272 VOID 273 ) 274 { 275 NTSTATUS Status; 276 ULONG Size; 277 278 /* Allocate 8 table entries */ 279 MmBlockAllocatorTableEntries = 8; 280 Size = sizeof(BL_BLOCK_DESCRIPTOR) * MmBlockAllocatorTableEntries; 281 MmBlockAllocatorTable = BlMmAllocateHeap(Size); 282 if (MmBlockAllocatorTable) 283 { 284 /* Zero them out -- we're all done */ 285 Status = STATUS_SUCCESS; 286 RtlZeroMemory(MmBlockAllocatorTable, Size); 287 MmBlockAllocatorInitialized = 1; 288 } 289 else 290 { 291 /* Bail out since we're out of memory */ 292 Status = STATUS_NO_MEMORY; 293 MmBlockAllocatorInitialized = 0; 294 } 295 296 /* Return initialization status */ 297 return Status; 298 } 299