/** Queues the event's notification function to fire. @param Event The Event to notify **/ VOID CoreNotifyEvent ( IN IEVENT *Event ) { // // Event database must be locked // ASSERT_LOCKED (&gEventQueueLock); // // If the event is queued somewhere, remove it // if (Event->NotifyLink.ForwardLink != NULL) { RemoveEntryList (&Event->NotifyLink); Event->NotifyLink.ForwardLink = NULL; } // // Queue the event to the pending notification list // InsertTailList (&gEventQueue[Event->NotifyTpl], &Event->NotifyLink); gEventPending |= (UINTN)(1 << Event->NotifyTpl); }
void MixerCore::InputFormatChanged(int32 inputID, const media_multi_audio_format &format) { ASSERT_LOCKED(); ERROR("MixerCore::InputFormatChanged not handled\n"); }
PCHAR DStreamNext(PDSTREAM pStream, PCHAR Buffer) { PLBUFFER lBuffer; PCHAR Next = NULL; ASSERT_DSTREAM(pStream); ASSERT_LOCKED(&pStream->Lock); if (Buffer) { lBuffer = CONTAINING_RECORD(Buffer, LBUFFER, Data); lBuffer = CONTAINING_RECORD(lBuffer->Entry.Flink, LBUFFER, Entry); Next = (PCHAR)&lBuffer->Data; } else { if (!IsListEmpty(&pStream->BufferListHead)) { lBuffer = CONTAINING_RECORD(pStream->BufferListHead.Flink, LBUFFER, Entry); Next = (PCHAR)&lBuffer->Data; } } // if (Buffer) return(Next); }
/** Inserts the timer event. @param Event Points to the internal structure of timer event to be installed **/ VOID CoreInsertEventTimer ( IN IEVENT *Event ) { UINT64 TriggerTime; LIST_ENTRY *Link; IEVENT *Event2; ASSERT_LOCKED (&mEfiTimerLock); // // Get the timer's trigger time // TriggerTime = Event->Timer.TriggerTime; // // Insert the timer into the timer database in assending sorted order // for (Link = mEfiTimerList.ForwardLink; Link != &mEfiTimerList; Link = Link->ForwardLink) { Event2 = CR (Link, IEVENT, Timer.Link, EVENT_SIGNATURE); if (Event2->Timer.TriggerTime > TriggerTime) { break; } } InsertTailList (Link, &Event->Timer.Link); }
VOID CoreNotifyProtocolEntry ( IN PROTOCOL_ENTRY *ProtEntry ) /*++ Routine Description: Signal event for every protocol in protocol entry. Arguments: ProtEntry - Protocol entry Returns: --*/ { PROTOCOL_NOTIFY *ProtNotify; EFI_LIST_ENTRY *Link; ASSERT_LOCKED (&gProtocolDatabaseLock); for (Link=ProtEntry->Notify.ForwardLink; Link != &ProtEntry->Notify; Link=Link->ForwardLink) { ProtNotify = CR(Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE); CoreSignalEvent (ProtNotify->Event); } }
PROTOCOL_INTERFACE * CoreRemoveInterfaceFromProtocol ( IN IHANDLE *Handle, IN EFI_GUID *Protocol, IN VOID *Interface ) /*++ Routine Description: Removes Protocol from the protocol list (but not the handle list). Arguments: Handle - The handle to remove protocol on. Protocol - GUID of the protocol to be moved Interface - The interface of the protocol Returns: Protocol Entry --*/ { PROTOCOL_INTERFACE *Prot; PROTOCOL_NOTIFY *ProtNotify; PROTOCOL_ENTRY *ProtEntry; EFI_LIST_ENTRY *Link; ASSERT_LOCKED (&gProtocolDatabaseLock); Prot = CoreFindProtocolInterface (Handle, Protocol, Interface); if (Prot != NULL) { ProtEntry = Prot->Protocol; // // If there's a protocol notify location pointing to this entry, back it up one // for(Link = ProtEntry->Notify.ForwardLink; Link != &ProtEntry->Notify; Link=Link->ForwardLink) { ProtNotify = CR(Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE); if (ProtNotify->Position == &Prot->ByProtocol) { ProtNotify->Position = Prot->ByProtocol.BackLink; } } // // Remove the protocol interface entry // RemoveEntryList (&Prot->ByProtocol); } return Prot; }
/** Finds the protocol entry for the requested protocol. The gProtocolDatabaseLock must be owned @param Protocol The ID of the protocol @param Create Create a new entry if not found @return Protocol entry **/ PROTOCOL_ENTRY * CoreFindProtocolEntry ( IN EFI_GUID *Protocol, IN BOOLEAN Create ) { LIST_ENTRY *Link; PROTOCOL_ENTRY *Item; PROTOCOL_ENTRY *ProtEntry; ASSERT_LOCKED(&gProtocolDatabaseLock); // // Search the database for the matching GUID // ProtEntry = NULL; for (Link = mProtocolDatabase.ForwardLink; Link != &mProtocolDatabase; Link = Link->ForwardLink) { Item = CR(Link, PROTOCOL_ENTRY, AllEntries, PROTOCOL_ENTRY_SIGNATURE); if (CompareGuid (&Item->ProtocolID, Protocol)) { // // This is the protocol entry // ProtEntry = Item; break; } } // // If the protocol entry was not found and Create is TRUE, then // allocate a new entry // if ((ProtEntry == NULL) && Create) { ProtEntry = AllocatePool (sizeof(PROTOCOL_ENTRY)); if (ProtEntry != NULL) { // // Initialize new protocol entry structure // ProtEntry->Signature = PROTOCOL_ENTRY_SIGNATURE; CopyGuid ((VOID *)&ProtEntry->ProtocolID, Protocol); InitializeListHead (&ProtEntry->Protocols); InitializeListHead (&ProtEntry->Notify); // // Add it to protocol database // InsertTailList (&mProtocolDatabase, &ProtEntry->AllEntries); } } return ProtEntry; }
MixerInput* MixerCore::AddInput(const media_input& input) { ASSERT_LOCKED(); MixerInput* in = new MixerInput(this, input, fMixBufferFrameRate, fMixBufferFrameCount); fInputs->AddItem(in); return in; }
void MixerCore::ApplyOutputFormat() { ASSERT_LOCKED(); media_multi_audio_format format = fOutput->MediaOutput().format.u.raw_audio; if (fMixBuffer != NULL) rtm_free(fMixBuffer); delete fMixBufferChannelTypes; fMixBufferFrameRate = (int32)(0.5 + format.frame_rate); fMixBufferFrameCount = frames_per_buffer(format); if (fDoubleRateMixing) { fMixBufferFrameRate *= 2; fMixBufferFrameCount *= 2; } fMixBufferChannelCount = format.channel_count; ASSERT(fMixBufferChannelCount == fOutput->GetOutputChannelCount()); fMixBufferChannelTypes = new int32 [format.channel_count]; for (int i = 0; i < fMixBufferChannelCount; i++) { fMixBufferChannelTypes[i] = ChannelMaskToChannelType(GetChannelMask(i, format.channel_mask)); } fMixBuffer = (float *)rtm_alloc(NULL, sizeof(float) * fMixBufferFrameCount * fMixBufferChannelCount); ASSERT(fMixBuffer); if (fResampler) { for (int i = 0; i < fMixBufferChannelCount; i++) delete fResampler[i]; delete [] fResampler; } fResampler = new Resampler * [fMixBufferChannelCount]; for (int i = 0; i < fMixBufferChannelCount; i++) { fResampler[i] = new Resampler(media_raw_audio_format::B_AUDIO_FLOAT, format.format); } TRACE("MixerCore::OutputFormatChanged:\n"); TRACE(" fMixBufferFrameRate %ld\n", fMixBufferFrameRate); TRACE(" fMixBufferFrameCount %ld\n", fMixBufferFrameCount); TRACE(" fMixBufferChannelCount %ld\n", fMixBufferChannelCount); for (int i = 0; i < fMixBufferChannelCount; i++) TRACE(" fMixBufferChannelTypes[%i] %ld\n", i, fMixBufferChannelTypes[i]); MixerInput *input; for (int i = 0; (input = Input(i)); i++) input->SetMixBufferFormat(fMixBufferFrameRate, fMixBufferFrameCount); }
void MixerCore::EnableOutput(bool enabled) { ASSERT_LOCKED(); TRACE("MixerCore::EnableOutput %d\n", enabled); fOutputEnabled = enabled; if (fRunning && !fOutputEnabled) StopMixThread(); if (!fRunning && fOutput && fStarted && fOutputEnabled) StartMixThread(); }
void MixerCore::SetTimingInfo(BTimeSource *ts, bigtime_t downstream_latency) { ASSERT_LOCKED(); if (fTimeSource) fTimeSource->Release(); fTimeSource = dynamic_cast<BTimeSource *>(ts->Acquire()); fDownstreamLatency = downstream_latency; TRACE("MixerCore::SetTimingInfo, now = %Ld, downstream latency %Ld\n", fTimeSource->Now(), fDownstreamLatency); }
void MixerCore::UpdateResamplingAlgorithm() { ASSERT_LOCKED(); _UpdateResamplers(fOutput->MediaOutput().format.u.raw_audio); for (int32 i = fInputs->CountItems() - 1; i >= 0; i--) { MixerInput* input = reinterpret_cast<MixerInput*>(fInputs->ItemAtFast(i)); input->UpdateResamplingAlgorithm(); } }
bool MixerCore::RemoveInput(int32 inputID) { ASSERT_LOCKED(); MixerInput *input; for (int i = 0; (input = Input(i)) != 0; i++) { if (input->ID() == inputID) { fInputs->RemoveItem(i); delete input; return true; } } return false; }
bool MixerCore::Stop() { ASSERT_LOCKED(); TRACE("MixerCore::Stop\n"); if (!fStarted) return false; if (fRunning) StopMixThread(); fStarted = false; return true; }
void MixerCore::OutputFormatChanged(const media_multi_audio_format &format) { ASSERT_LOCKED(); bool was_started = fStarted; if (was_started) Stop(); fOutput->ChangeFormat(format); _ApplyOutputFormat(); if (was_started) Start(); }
void MixerCore::BufferReceived(BBuffer *buffer, bigtime_t lateness) { ASSERT_LOCKED(); MixerInput *input; int32 id = buffer->Header()->destination; for (int i = 0; (input = Input(i)) != 0; i++) { if (input->ID() == id) { input->BufferReceived(buffer); return; } } ERROR("MixerCore::BufferReceived: received buffer for unknown id %ld\n", id); }
bool MixerCore::RemoveOutput() { ASSERT_LOCKED(); if (!fOutput) return false; if (fStarted) StopMixThread(); delete fOutput; fOutput = 0; fOutputEnabled = true; return true; }
/** Signal event for every protocol in protocol entry. @param ProtEntry Protocol entry **/ VOID CoreNotifyProtocolEntry ( IN PROTOCOL_ENTRY *ProtEntry ) { PROTOCOL_NOTIFY *ProtNotify; LIST_ENTRY *Link; ASSERT_LOCKED (&gProtocolDatabaseLock); for (Link=ProtEntry->Notify.ForwardLink; Link != &ProtEntry->Notify; Link=Link->ForwardLink) { ProtNotify = CR(Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE); CoreSignalEvent (ProtNotify->Event); } }
MixerOutput* MixerCore::AddOutput(const media_output& output) { ASSERT_LOCKED(); if (fOutput) { ERROR("MixerCore::AddOutput: already connected\n"); return fOutput; } fOutput = new MixerOutput(this, output); // the output format might have been adjusted inside MixerOutput _ApplyOutputFormat(); ASSERT(!fRunning); if (fStarted && fOutputEnabled) StartMixThread(); return fOutput; }
bool MixerCore::Start() { ASSERT_LOCKED(); TRACE("MixerCore::Start\n"); if (fStarted) return false; fStarted = true; ASSERT(!fRunning); // only start the mix thread if we have an output if (fOutput && fOutputEnabled) StartMixThread(); return true; }
VOID STATIC CoreNotifyEvent ( IN IEVENT *Event ) /*++ Routine Description: Queues the event's notification function to fire Arguments: Event - The Event to notify Returns: None --*/ { // // Event database must be locked // ASSERT_LOCKED (&gEventQueueLock); // // If the event is queued somewhere, remove it // if (Event->NotifyLink.ForwardLink != NULL) { RemoveEntryList (&Event->NotifyLink); Event->NotifyLink.ForwardLink = NULL; } // // Queue the event to the pending notification list // InsertTailList (&gEventQueue[Event->NotifyTpl], &Event->NotifyLink); gEventPending |= (UINTN)1 << Event->NotifyTpl; }
VOID SEnvSortVarList ( IN EFI_LIST_ENTRY *Head ) /*++ Routine Description: Arguments: Head - The variable list head Returns: --*/ { ASSERT_LOCKED (&SEnvLock); return ; }
/** Finds the protocol instance for the requested handle and protocol. Note: This function doesn't do parameters checking, it's caller's responsibility to pass in valid parameters. @param Handle The handle to search the protocol on @param Protocol GUID of the protocol @param Interface The interface for the protocol being searched @return Protocol instance (NULL: Not found) **/ PROTOCOL_INTERFACE * CoreFindProtocolInterface ( IN IHANDLE *Handle, IN EFI_GUID *Protocol, IN VOID *Interface ) { PROTOCOL_INTERFACE *Prot; PROTOCOL_ENTRY *ProtEntry; LIST_ENTRY *Link; ASSERT_LOCKED(&gProtocolDatabaseLock); Prot = NULL; // // Lookup the protocol entry for this protocol ID // ProtEntry = CoreFindProtocolEntry (Protocol, FALSE); if (ProtEntry != NULL) { // // Look at each protocol interface for any matches // for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link=Link->ForwardLink) { // // If this protocol interface matches, remove it // Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE); if (Prot->Interface == Interface && Prot->Protocol == ProtEntry) { break; } Prot = NULL; } } return Prot; }
/** Removes Protocol from the protocol list (but not the handle list). @param Handle The handle to remove protocol on. @param Protocol GUID of the protocol to be moved @param Interface The interface of the protocol @return Protocol Entry **/ PROTOCOL_INTERFACE * CoreRemoveInterfaceFromProtocol ( IN IHANDLE *Handle, IN EFI_GUID *Protocol, IN VOID *Interface ) { PROTOCOL_INTERFACE *Prot; PROTOCOL_NOTIFY *ProtNotify; PROTOCOL_ENTRY *ProtEntry; LIST_ENTRY *Link; ASSERT_LOCKED (&gProtocolDatabaseLock); Prot = CoreFindProtocolInterface (Handle, Protocol, Interface); if (Prot != NULL) { ProtEntry = Prot->Protocol; // // If there's a protocol notify location pointing to this entry, back it up one // for(Link = ProtEntry->Notify.ForwardLink; Link != &ProtEntry->Notify; Link=Link->ForwardLink) { ProtNotify = CR(Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE); if (ProtNotify->Position == &Prot->ByProtocol) { ProtNotify->Position = Prot->ByProtocol.BackLink; } } // // Remove the protocol interface entry // RemoveEntryList (&Prot->ByProtocol); } return Prot; }
void MixerCore::_UpdateResamplers(const media_multi_audio_format& format) { ASSERT_LOCKED(); if (fResampler != NULL) { for (int i = 0; i < fMixBufferChannelCount; i++) delete fResampler[i]; delete[] fResampler; } fResampler = new Resampler*[fMixBufferChannelCount]; for (int i = 0; i < fMixBufferChannelCount; i++) { switch (Settings()->ResamplingAlgorithm()) { case 2: fResampler[i] = new Interpolate( media_raw_audio_format::B_AUDIO_FLOAT, format.format); break; default: fResampler[i] = new Resampler( media_raw_audio_format::B_AUDIO_FLOAT, format.format); } } }
/** Internal function. Converts a memory range to the specified type. The range must exist in the memory map. @param Start The first address of the range Must be page aligned @param NumberOfPages The number of pages to convert @param NewType The new type for the memory range @retval EFI_INVALID_PARAMETER Invalid parameter @retval EFI_NOT_FOUND Could not find a descriptor cover the specified range or convertion not allowed. @retval EFI_SUCCESS Successfully converts the memory range to the specified type. **/ EFI_STATUS CoreConvertPages ( IN UINT64 Start, IN UINT64 NumberOfPages, IN EFI_MEMORY_TYPE NewType ) { UINT64 NumberOfBytes; UINT64 End; UINT64 RangeEnd; UINT64 Attribute; LIST_ENTRY *Link; MEMORY_MAP *Entry; Entry = NULL; NumberOfBytes = LShiftU64 (NumberOfPages, EFI_PAGE_SHIFT); End = Start + NumberOfBytes - 1; ASSERT (NumberOfPages); ASSERT ((Start & EFI_PAGE_MASK) == 0); ASSERT (End > Start) ; ASSERT_LOCKED (&gMemoryLock); if (NumberOfPages == 0 || ((Start & EFI_PAGE_MASK) != 0) || (Start > (Start + NumberOfBytes))) { return EFI_INVALID_PARAMETER; } // // Convert the entire range // while (Start < End) { // // Find the entry that the covers the range // for (Link = gMemoryMap.ForwardLink; Link != &gMemoryMap; Link = Link->ForwardLink) { Entry = CR (Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE); if (Entry->Start <= Start && Entry->End > Start) { break; } } if (Link == &gMemoryMap) { DEBUG ((DEBUG_ERROR | DEBUG_PAGE, "ConvertPages: failed to find range %lx - %lx\n", Start, End)); return EFI_NOT_FOUND; } // // Convert range to the end, or to the end of the descriptor // if that's all we've got // RangeEnd = End; ASSERT (Entry != NULL); if (Entry->End < End) { RangeEnd = Entry->End; } DEBUG ((DEBUG_PAGE, "ConvertRange: %lx-%lx to %d\n", Start, RangeEnd, NewType)); // // Debug code - verify conversion is allowed // if (!(NewType == EfiConventionalMemory ? 1 : 0) ^ (Entry->Type == EfiConventionalMemory ? 1 : 0)) { DEBUG ((DEBUG_ERROR | DEBUG_PAGE, "ConvertPages: Incompatible memory types\n")); return EFI_NOT_FOUND; } // // Update counters for the number of pages allocated to each memory type // if (Entry->Type >= 0 && Entry->Type < EfiMaxMemoryType) { if (Start >= mMemoryTypeStatistics[Entry->Type].BaseAddress && Start <= mMemoryTypeStatistics[Entry->Type].MaximumAddress) { if (NumberOfPages > mMemoryTypeStatistics[Entry->Type].CurrentNumberOfPages) { mMemoryTypeStatistics[Entry->Type].CurrentNumberOfPages = 0; } else { mMemoryTypeStatistics[Entry->Type].CurrentNumberOfPages -= NumberOfPages; } } } if (NewType >= 0 && NewType < EfiMaxMemoryType) { if (Start >= mMemoryTypeStatistics[NewType].BaseAddress && Start <= mMemoryTypeStatistics[NewType].MaximumAddress) { mMemoryTypeStatistics[NewType].CurrentNumberOfPages += NumberOfPages; if (mMemoryTypeStatistics[NewType].CurrentNumberOfPages > gMemoryTypeInformation[mMemoryTypeStatistics[NewType].InformationIndex].NumberOfPages) { gMemoryTypeInformation[mMemoryTypeStatistics[NewType].InformationIndex].NumberOfPages = (UINT32)mMemoryTypeStatistics[NewType].CurrentNumberOfPages; } } } // // Pull range out of descriptor // if (Entry->Start == Start) { // // Clip start // Entry->Start = RangeEnd + 1; } else if (Entry->End == RangeEnd) { // // Clip end // Entry->End = Start - 1; } else { // // Pull it out of the center, clip current // // // Add a new one // mMapStack[mMapDepth].Signature = MEMORY_MAP_SIGNATURE; mMapStack[mMapDepth].FromPages = FALSE; mMapStack[mMapDepth].Type = Entry->Type; mMapStack[mMapDepth].Start = RangeEnd+1; mMapStack[mMapDepth].End = Entry->End; // // Inherit Attribute from the Memory Descriptor that is being clipped // mMapStack[mMapDepth].Attribute = Entry->Attribute; Entry->End = Start - 1; ASSERT (Entry->Start < Entry->End); Entry = &mMapStack[mMapDepth]; InsertTailList (&gMemoryMap, &Entry->Link); mMapDepth += 1; ASSERT (mMapDepth < MAX_MAP_DEPTH); } // // The new range inherits the same Attribute as the Entry //it is being cut out of // Attribute = Entry->Attribute; // // If the descriptor is empty, then remove it from the map // if (Entry->Start == Entry->End + 1) { RemoveMemoryMapEntry (Entry); Entry = NULL; } // // Add our new range in // CoreAddRange (NewType, Start, RangeEnd, Attribute); // // Move any map descriptor stack to general pool // CoreFreeMemoryMapStack (); // // Bump the starting address, and convert the next range // Start = RangeEnd + 1; } // // Converted the whole range, done // return EFI_SUCCESS; }
/** Internal function. Moves any memory descriptors that are on the temporary descriptor stack to heap. **/ VOID CoreFreeMemoryMapStack ( VOID ) { MEMORY_MAP *Entry; MEMORY_MAP *Entry2; LIST_ENTRY *Link2; ASSERT_LOCKED (&gMemoryLock); // // If already freeing the map stack, then return // if (mFreeMapStack != 0) { return ; } // // Move the temporary memory descriptor stack into pool // mFreeMapStack += 1; while (mMapDepth != 0) { // // Deque an memory map entry from mFreeMemoryMapEntryList // Entry = AllocateMemoryMapEntry (); ASSERT (Entry); // // Update to proper entry // mMapDepth -= 1; if (mMapStack[mMapDepth].Link.ForwardLink != NULL) { // // Move this entry to general memory // RemoveEntryList (&mMapStack[mMapDepth].Link); mMapStack[mMapDepth].Link.ForwardLink = NULL; CopyMem (Entry , &mMapStack[mMapDepth], sizeof (MEMORY_MAP)); Entry->FromPages = TRUE; // // Find insertion location // for (Link2 = gMemoryMap.ForwardLink; Link2 != &gMemoryMap; Link2 = Link2->ForwardLink) { Entry2 = CR (Link2, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE); if (Entry2->FromPages && Entry2->Start > Entry->Start) { break; } } InsertTailList (Link2, &Entry->Link); } else { // // This item of mMapStack[mMapDepth] has already been dequeued from gMemoryMap list, // so here no need to move it to memory. // InsertTailList (&mFreeMemoryMapEntryList, &Entry->Link); } } mFreeMapStack -= 1; }
/** Internal function. Adds a ranges to the memory map. The range must not already exist in the map. @param Type The type of memory range to add @param Start The starting address in the memory range Must be paged aligned @param End The last address in the range Must be the last byte of a page @param Attribute The attributes of the memory range to add **/ VOID CoreAddRange ( IN EFI_MEMORY_TYPE Type, IN EFI_PHYSICAL_ADDRESS Start, IN EFI_PHYSICAL_ADDRESS End, IN UINT64 Attribute ) { LIST_ENTRY *Link; MEMORY_MAP *Entry; ASSERT ((Start & EFI_PAGE_MASK) == 0); ASSERT (End > Start) ; ASSERT_LOCKED (&gMemoryLock); DEBUG ((DEBUG_PAGE, "AddRange: %lx-%lx to %d\n", Start, End, Type)); // // Memory map being altered so updated key // mMemoryMapKey += 1; // // UEFI 2.0 added an event group for notificaiton on memory map changes. // So we need to signal this Event Group every time the memory map changes. // If we are in EFI 1.10 compatability mode no event groups will be // found and nothing will happen we we call this function. These events // will get signaled but since a lock is held around the call to this // function the notificaiton events will only be called after this funciton // returns and the lock is released. // CoreNotifySignalList (&gEfiEventMemoryMapChangeGuid); // // Look for adjoining memory descriptor // // Two memory descriptors can only be merged if they have the same Type // and the same Attribute // Link = gMemoryMap.ForwardLink; while (Link != &gMemoryMap) { Entry = CR (Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE); Link = Link->ForwardLink; if (Entry->Type != Type) { continue; } if (Entry->Attribute != Attribute) { continue; } if (Entry->End + 1 == Start) { Start = Entry->Start; RemoveMemoryMapEntry (Entry); } else if (Entry->Start == End + 1) { End = Entry->End; RemoveMemoryMapEntry (Entry); } } // // Add descriptor // mMapStack[mMapDepth].Signature = MEMORY_MAP_SIGNATURE; mMapStack[mMapDepth].FromPages = FALSE; mMapStack[mMapDepth].Type = Type; mMapStack[mMapDepth].Start = Start; mMapStack[mMapDepth].End = End; mMapStack[mMapDepth].VirtualStart = 0; mMapStack[mMapDepth].Attribute = Attribute; InsertTailList (&gMemoryMap, &mMapStack[mMapDepth].Link); mMapDepth += 1; ASSERT (mMapDepth < MAX_MAP_DEPTH); return ; }
/** Internal function to allocate pool of a particular type. Caller must have the memory lock held @param PoolType Type of pool to allocate @param Size The amount of pool to allocate @param NeedGuard Flag to indicate Guard page is needed or not @return The allocate pool, or NULL **/ VOID * CoreAllocatePoolI ( IN EFI_MEMORY_TYPE PoolType, IN UINTN Size, IN BOOLEAN NeedGuard ) { POOL *Pool; POOL_FREE *Free; POOL_HEAD *Head; POOL_TAIL *Tail; CHAR8 *NewPage; VOID *Buffer; UINTN Index; UINTN FSize; UINTN Offset, MaxOffset; UINTN NoPages; UINTN Granularity; BOOLEAN HasPoolTail; ASSERT_LOCKED (&mPoolMemoryLock); if (PoolType == EfiACPIReclaimMemory || PoolType == EfiACPIMemoryNVS || PoolType == EfiRuntimeServicesCode || PoolType == EfiRuntimeServicesData) { Granularity = RUNTIME_PAGE_ALLOCATION_GRANULARITY; } else { Granularity = DEFAULT_PAGE_ALLOCATION_GRANULARITY; } // // Adjust the size by the pool header & tail overhead // HasPoolTail = !(NeedGuard && ((PcdGet8 (PcdHeapGuardPropertyMask) & BIT7) == 0)); // // Adjusting the Size to be of proper alignment so that // we don't get an unaligned access fault later when // pool_Tail is being initialized // Size = ALIGN_VARIABLE (Size); Size += POOL_OVERHEAD; Index = SIZE_TO_LIST(Size); Pool = LookupPoolHead (PoolType); if (Pool== NULL) { return NULL; } Head = NULL; // // If allocation is over max size, just allocate pages for the request // (slow) // if (Index >= SIZE_TO_LIST (Granularity) || NeedGuard) { if (!HasPoolTail) { Size -= sizeof (POOL_TAIL); } NoPages = EFI_SIZE_TO_PAGES (Size) + EFI_SIZE_TO_PAGES (Granularity) - 1; NoPages &= ~(UINTN)(EFI_SIZE_TO_PAGES (Granularity) - 1); Head = CoreAllocatePoolPagesI (PoolType, NoPages, Granularity, NeedGuard); if (NeedGuard) { Head = AdjustPoolHeadA ((EFI_PHYSICAL_ADDRESS)(UINTN)Head, NoPages, Size); } goto Done; } // // If there's no free pool in the proper list size, go get some more pages // if (IsListEmpty (&Pool->FreeList[Index])) { Offset = LIST_TO_SIZE (Index); MaxOffset = Granularity; // // Check the bins holding larger blocks, and carve one up if needed // while (++Index < SIZE_TO_LIST (Granularity)) { if (!IsListEmpty (&Pool->FreeList[Index])) { Free = CR (Pool->FreeList[Index].ForwardLink, POOL_FREE, Link, POOL_FREE_SIGNATURE); RemoveEntryList (&Free->Link); NewPage = (VOID *) Free; MaxOffset = LIST_TO_SIZE (Index); goto Carve; } } // // Get another page // NewPage = CoreAllocatePoolPagesI (PoolType, EFI_SIZE_TO_PAGES (Granularity), Granularity, NeedGuard); if (NewPage == NULL) { goto Done; } // // Serve the allocation request from the head of the allocated block // Carve: Head = (POOL_HEAD *) NewPage; // // Carve up remaining space into free pool blocks // Index--; while (Offset < MaxOffset) { ASSERT (Index < MAX_POOL_LIST); FSize = LIST_TO_SIZE(Index); while (Offset + FSize <= MaxOffset) { Free = (POOL_FREE *) &NewPage[Offset]; Free->Signature = POOL_FREE_SIGNATURE; Free->Index = (UINT32)Index; InsertHeadList (&Pool->FreeList[Index], &Free->Link); Offset += FSize; } Index -= 1; } ASSERT (Offset == MaxOffset); goto Done; } // // Remove entry from free pool list // Free = CR (Pool->FreeList[Index].ForwardLink, POOL_FREE, Link, POOL_FREE_SIGNATURE); RemoveEntryList (&Free->Link); Head = (POOL_HEAD *) Free; Done: Buffer = NULL; if (Head != NULL) { // // Account the allocation // Pool->Used += Size; // // If we have a pool buffer, fill in the header & tail info // Head->Signature = POOL_HEAD_SIGNATURE; Head->Size = Size; Head->Type = (EFI_MEMORY_TYPE) PoolType; Buffer = Head->Data; if (HasPoolTail) { Tail = HEAD_TO_TAIL (Head); Tail->Signature = POOL_TAIL_SIGNATURE; Tail->Size = Size; Size -= POOL_OVERHEAD; } else { Size -= SIZE_OF_POOL_HEAD; } DEBUG_CLEAR_MEMORY (Buffer, Size); DEBUG (( DEBUG_POOL, "AllocatePoolI: Type %x, Addr %p (len %lx) %,ld\n", PoolType, Buffer, (UINT64)Size, (UINT64) Pool->Used )); } else { DEBUG ((DEBUG_ERROR | DEBUG_POOL, "AllocatePool: failed to allocate %ld bytes\n", (UINT64) Size)); } return Buffer; }
VOID DStreamUnlock(PDSTREAM pStream) { ASSERT_DSTREAM(pStream); ASSERT_LOCKED(&pStream->Lock); KeReleaseSpinLock(&pStream->Lock, pStream->OldIrql); }