diff options
author | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
---|---|---|
committer | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
commit | e611b132f9b8abe35b362e5870b74bce94a1e58e (patch) | |
tree | a5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/nthals/halalpha/memory.c | |
download | NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2 NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip |
Diffstat (limited to 'private/ntos/nthals/halalpha/memory.c')
-rw-r--r-- | private/ntos/nthals/halalpha/memory.c | 575 |
1 files changed, 575 insertions, 0 deletions
diff --git a/private/ntos/nthals/halalpha/memory.c b/private/ntos/nthals/halalpha/memory.c new file mode 100644 index 000000000..306b9be61 --- /dev/null +++ b/private/ntos/nthals/halalpha/memory.c @@ -0,0 +1,575 @@ +/*++ + +Copyright (c) 1992, 1993 Digital Equipment Corporation + +Module Name: + + memory.c + +Abstract: + + Provides routines to allow tha HAL to map physical memory + +Author: + + Jeff McLeman (DEC) 11-June-1992 + +Revision History: + + Joe Notarangelo 20-Oct-1993 + - Fix bug where physical address was rounded up without referencing + AlignmentOffset, resulting in an incorrect physical address + - Remove magic numbers + - Create a routine to dump all of the descriptors to the debugger + +Environment: + + Phase 0 initialization only + +--*/ + +#include "halp.h" + +#define __1KB (1024) + +MEMORY_ALLOCATION_DESCRIPTOR HalpExtraAllocationDescriptor; + + + +ULONG +HalpAllocPhysicalMemory( + IN PLOADER_PARAMETER_BLOCK LoaderBlock, + IN ULONG MaxPhysicalAddress, + IN ULONG NoPages, + IN BOOLEAN AlignOn64k + ) +/*++ + +Routine Description: + + Carves out N pages of physical memory from the memory descriptor + list in the desired location. This function is to be called only + during phase zero initialization. (ie, before the kernel's memory + management system is running) + +Arguments: + + LoaderBlock - Supplies a pointer to the loader parameter block which + contains the system memory descriptors. + + MaxPhysicalAddress - Supplies the maximum address below which the memory + must be allocated. + + NoPages - Supplies the number of pages to allocate. + + AlignOn64k - Supplies a boolean that specifies if the requested memory + allocation must start on a 64K boundary. + +Return Value: + + The pyhsical address or NULL if the memory could not be obtained. + +--*/ +{ + ULONG AlignmentMask; + ULONG AlignmentOffset; + PMEMORY_ALLOCATION_DESCRIPTOR BestFitDescriptor; + ULONG BestFitAlignmentOffset; + PMEMORY_ALLOCATION_DESCRIPTOR Descriptor; + PLIST_ENTRY NextMd; + ULONG MaxPageAddress; + ULONG PhysicalAddress; + + MaxPageAddress = MaxPhysicalAddress >> PAGE_SHIFT; + + AlignmentMask = (__64K >> PAGE_SHIFT) - 1; + + BestFitDescriptor = NULL; + BestFitAlignmentOffset = AlignmentMask + 1; + + // + // Scan the memory allocation descriptors for an eligible descriptor from + // which we can allocate the requested block of memory. + // + + NextMd = LoaderBlock->MemoryDescriptorListHead.Flink; + while (NextMd != &LoaderBlock->MemoryDescriptorListHead) { + Descriptor = CONTAINING_RECORD(NextMd, + MEMORY_ALLOCATION_DESCRIPTOR, + ListEntry); + + if( AlignOn64k ){ + + AlignmentOffset = + ((Descriptor->BasePage + AlignmentMask) & ~AlignmentMask) - + Descriptor->BasePage; + + } else { + + AlignmentOffset = 0; + + } + + // + // Search for a block of memory which is contains a memory chunk + // that is greater than size pages, and has a physical address less + // than MAXIMUM_PHYSICAL_ADDRESS. + // + + if ((Descriptor->MemoryType == LoaderFree || + Descriptor->MemoryType == MemoryFirmwareTemporary) && + (Descriptor->PageCount >= NoPages + AlignmentOffset) && + (Descriptor->BasePage + NoPages + AlignmentOffset < + MaxPageAddress) ) + { + + // + // Check for a perfect fit where we need not split the descriptor + // because AlignmentOffset == 0. No need to search further if + // there is a perfect fit. + // + + if( AlignmentOffset == 0 ){ + BestFitDescriptor = Descriptor; + BestFitAlignmentOffset = AlignmentOffset; + break; + } + + // + // If not a perfect fit check for the best fit so far. + // + + if( AlignmentOffset < BestFitAlignmentOffset ){ + BestFitDescriptor = Descriptor; + BestFitAlignmentOffset = AlignmentOffset; + } + + } + + NextMd = NextMd->Flink; + } + + // + // Verify that we have found an eligible descriptor. + // + + ASSERT( BestFitDescriptor != NULL ); + + if( BestFitDescriptor == NULL ){ + return (ULONG)NULL; + } + + // + // Compute the physical address of the memory block we have found. + // + + PhysicalAddress = (BestFitDescriptor->BasePage + BestFitAlignmentOffset) + << PAGE_SHIFT; + // + // Adjust the memory descriptors to account for the memory we have + // allocated. + // + + if (BestFitAlignmentOffset == 0) { + + BestFitDescriptor->BasePage += NoPages; + BestFitDescriptor->PageCount -= NoPages; + + if (BestFitDescriptor->PageCount == 0) { + + // + // The whole block was allocated, + // Remove the entry from the list completely. + // + + RemoveEntryList(&BestFitDescriptor->ListEntry); + + } + + } else { + + // + // The descriptor will be split into 3 pieces, the beginning + // segment up to our allocation, our allocation, and the trailing + // segment. We have one spare memory descriptor to handle this + // case, use it if it is not already used otherwise preserve as + // much memory as possible. + // + + if( (BestFitDescriptor->PageCount - NoPages - BestFitAlignmentOffset) + == 0 ){ + + // + // The third segment is empty, use the original descriptor to + // map the first segment. + // + + BestFitDescriptor->PageCount -= NoPages; + + } else { + + if( HalpExtraAllocationDescriptor.PageCount == 0 ){ + + // + // The extra descriptor can be used to map the third segment. + // + + HalpExtraAllocationDescriptor.PageCount = + BestFitDescriptor->PageCount - NoPages - + BestFitAlignmentOffset; + + HalpExtraAllocationDescriptor.BasePage = + BestFitDescriptor->BasePage + NoPages + + BestFitAlignmentOffset; + + HalpExtraAllocationDescriptor.MemoryType = MemoryFree; + + InsertTailList( + &BestFitDescriptor->ListEntry, + &HalpExtraAllocationDescriptor.ListEntry ); + + // + // Use the original descriptor to map the first segment. + // + + BestFitDescriptor->PageCount = BestFitAlignmentOffset; + + } else { + + // + // We need to split the original descriptor into 3 segments + // but we've already used the spare descriptor. Use the + // original descriptor to map the largest segment. + // + + ULONG WastedPages; + + if( (BestFitDescriptor->PageCount - BestFitAlignmentOffset - + NoPages) > BestFitAlignmentOffset ){ + + WastedPages = BestFitAlignmentOffset; + + // + // Map the third segment using the original descriptor. + // + + BestFitDescriptor->BasePage += BestFitAlignmentOffset + + NoPages; + BestFitDescriptor->PageCount -= BestFitAlignmentOffset + + NoPages; + + } else { + + WastedPages = BestFitDescriptor->PageCount - + BestFitAlignmentOffset - NoPages; + + // + // Map the first segment using the original descriptor. + // + + BestFitDescriptor->PageCount = BestFitAlignmentOffset; + + } //end if( (BestFitDescriptor->PageCount - BestFitAlignm ... + + // + // Report that we have had to waste pages. + // + + DbgPrint( "HalpAllocPhysicalMemory: wasting %d pages\n", + WastedPages ); + + } //end if( HalpExtraAllocationDescriptor.PageCount == 0 ) + + } //end if( (BestFitDescriptor->PageCount - NoPages - BestFitAlign ... + + } //end if (BestFitAlignmentOffset == 0) + + + return PhysicalAddress; +} + +ULONGLONG +HalpGetMemorySize( + IN PLOADER_PARAMETER_BLOCK LoaderBlock + ) +/*++ + +Routine Description: + + Computes the size of the memory from the descriptor list. + +Arguments: + + LoaderBlock - Supplies a pointer to the loader parameter block. + + +Return Value: + + Size of Memory in Bytes. + +--*/ +{ + PMEMORY_ALLOCATION_DESCRIPTOR Descriptor; + PLIST_ENTRY NextMd; + ULONG PageCounts = 0; + + // + // Scan the memory allocation descriptors and + // compute the Total pagecount + // + + NextMd = LoaderBlock->MemoryDescriptorListHead.Flink; + while (NextMd != &LoaderBlock->MemoryDescriptorListHead) { + + Descriptor = CONTAINING_RECORD(NextMd, + MEMORY_ALLOCATION_DESCRIPTOR, + ListEntry); + + // + // ignore bad memory descriptors. + // + if(Descriptor->MemoryType != LoaderBad){ + PageCounts += Descriptor->PageCount; + } + + + NextMd = NextMd->Flink; + } + + return (PageCounts << PAGE_SHIFT) ; + +} + +TYPE_OF_MEMORY +HalpGetMemoryType ( + IN PLOADER_PARAMETER_BLOCK LoaderBlock, + IN ULONG PageAddress, + OUT PULONG EndPageAddressInDesc + ) + +/*++ + +Routine Description: + + This routine checks to see how the specified address is mapped. + +Arguments: + + LoaderBlock - Supplies a pointer to the loader parameter block. + + PageAddress - The page address of memory to probe. + +Return Value: + + The memory type of the specified address, if it is mapped. If the + address is not mapped, then LoaderMaximum is returned. + +--*/ + +{ + PMEMORY_ALLOCATION_DESCRIPTOR Descriptor; + PLIST_ENTRY NextMd; + ULONG PageCounts = 0; + TYPE_OF_MEMORY MemoryType = LoaderMaximum; + + NextMd = LoaderBlock->MemoryDescriptorListHead.Flink; + while (NextMd != &LoaderBlock->MemoryDescriptorListHead) { + + Descriptor = CONTAINING_RECORD(NextMd, + MEMORY_ALLOCATION_DESCRIPTOR, + ListEntry); + + if ((PageAddress >= Descriptor->BasePage) && + (PageAddress < + Descriptor->BasePage + Descriptor->PageCount)) { + + MemoryType = Descriptor->MemoryType; + *EndPageAddressInDesc = Descriptor->BasePage + + Descriptor->PageCount - 1; + break; // we found the descriptor. + } + + NextMd = NextMd->Flink; + } + return MemoryType; +} + + +ULONGLONG +HalpGetContiguousMemorySize( + IN PLOADER_PARAMETER_BLOCK LoaderBlock + ) +/*++ + +Routine Description: + + Computes the size of initial contiguous memory from the + descriptor list. Contiguous memory means, that there is + no hole or Bad memory in this range. + +Arguments: + + LoaderBlock - Supplies a pointer to the loader parameter block. + + +Return Value: + + Size of Memory in Bytes. + +--*/ +{ + PMEMORY_ALLOCATION_DESCRIPTOR Descriptor; + PLIST_ENTRY NextMd; + ULONG PageCounts = 0; + TYPE_OF_MEMORY MemoryType; + ULONG EndPageAddressInDesc = 0; + + // + // Start from Page Address 0 and go until we hit a page + // with no descriptor or Bad Descriptor. + // + + MemoryType = HalpGetMemoryType(LoaderBlock, + PageCounts, + &EndPageAddressInDesc + ); + while(MemoryType != LoaderMaximum && MemoryType != LoaderBad){ + PageCounts = EndPageAddressInDesc + 1; + MemoryType = HalpGetMemoryType(LoaderBlock, + PageCounts, + &EndPageAddressInDesc + ); + } + + return (PageCounts << PAGE_SHIFT) ; + +} + + +#if HALDBG + + +VOID +HalpDumpMemoryDescriptors( + IN PLOADER_PARAMETER_BLOCK LoaderBlock + ) +/*++ + +Routine Description: + + Print the contents of the memory descriptors built by the + firmware and OS loader and passed through to the kernel. + This routine is intended as a sanity check that the descriptors + have been prepared properly and that no memory has been wasted. + +Arguments: + + LoaderBlock - Supplies a pointer to the loader parameter block. + + +Return Value: + + None. + +--*/ +{ + PMEMORY_ALLOCATION_DESCRIPTOR Descriptor; + PLIST_ENTRY NextMd; + ULONG PageCounts[LoaderMaximum]; + PCHAR MemoryTypeStrings[] = { + "ExceptionBlock", + "SystemBlock", + "Free", + "Bad", + "LoadedProgram", + "FirmwareTemporary", + "FirmwarePermanent", + "OsloaderHeap", + "OsloaderStack", + "SystemCode", + "HalCode", + "BootDriver", + "ConsoleInDriver", + "ConsoleOutDriver", + "StartupDpcStack", + "StartupKernelStack", + "StartupPanicStack", + "StartupPcrPage", + "StartupPdrPage", + "RegistryData", + "MemoryData", + "NlsData", + "SpecialMemory" + }; + ULONG i; + + // + // Clear the summary information structure. + // + + RtlZeroMemory( PageCounts, sizeof(ULONG) * LoaderMaximum ); + + // + // Scan the memory allocation descriptors print each descriptor and + // collect summary information. + // + + NextMd = LoaderBlock->MemoryDescriptorListHead.Flink; + while (NextMd != &LoaderBlock->MemoryDescriptorListHead) { + + Descriptor = CONTAINING_RECORD(NextMd, + MEMORY_ALLOCATION_DESCRIPTOR, + ListEntry); + + if( (Descriptor->MemoryType >= LoaderExceptionBlock) && + (Descriptor->MemoryType < LoaderMaximum) ) + { + + PageCounts[Descriptor->MemoryType] += Descriptor->PageCount; + DbgPrint( "%08x: %08x Type = %s\n", + (Descriptor->BasePage << PAGE_SHIFT) | KSEG0_BASE, + ( ( (Descriptor->BasePage + Descriptor->PageCount) + << PAGE_SHIFT) - 1) | KSEG0_BASE, + MemoryTypeStrings[Descriptor->MemoryType] ); + + + } else { + + DbgPrint( "%08x: %08x Unrecognized Memory Type = %x\n", + (Descriptor->BasePage << PAGE_SHIFT) | KSEG0_BASE, + ( ( (Descriptor->BasePage + Descriptor->PageCount) + << PAGE_SHIFT) - 1) | KSEG0_BASE, + Descriptor->MemoryType ); + + DbgPrint( "Unrecognized memory type\n" ); + + } + + NextMd = NextMd->Flink; + } + + + // + // Print the summary information. + // + + for( i=LoaderExceptionBlock; i<LoaderMaximum; i++ ){ + + // + // Only print those memory types that have non-zero allocations. + // + + if( PageCounts[i] != 0 ){ + + DbgPrint( "%8dK %s\n", + (PageCounts[i] << PAGE_SHIFT) / __1K, + MemoryTypeStrings[i] ); + + } + + } + + return; +} + +#endif //HALDBG |