/** Free FvDevice resource when error happens @param FvDevice pointer to the FvDevice to be freed. **/ VOID FreeFvDeviceResource ( IN FV_DEVICE *FvDevice ) { FFS_FILE_LIST_ENTRY *FfsFileEntry; LIST_ENTRY *NextEntry; // // Free File List Entry // FfsFileEntry = (FFS_FILE_LIST_ENTRY *)FvDevice->FfsFileListHeader.ForwardLink; while (&FfsFileEntry->Link != &FvDevice->FfsFileListHeader) { NextEntry = (&FfsFileEntry->Link)->ForwardLink; if (FfsFileEntry->StreamHandle != 0) { // // Close stream and free resources from SEP // CloseSectionStream (FfsFileEntry->StreamHandle, FALSE); } if (FfsFileEntry->FileCached) { // // Free the cached file buffer. // CoreFreePool (FfsFileEntry->FfsHeader); } CoreFreePool (FfsFileEntry); FfsFileEntry = (FFS_FILE_LIST_ENTRY *) NextEntry; } if (!FvDevice->IsMemoryMapped) { // // Free the cached FV buffer. // CoreFreePool (FvDevice->CachedFv); } // // Free Volume Header // CoreFreePool (FvDevice->FwVolHeader); return; }
/** Removes and frees an entry from the DebugImageInfo Table. @param ImageHandle image handle for the image being unloaded **/ VOID CoreRemoveDebugImageInfoEntry ( EFI_HANDLE ImageHandle ) { EFI_DEBUG_IMAGE_INFO *Table; UINTN Index; mDebugInfoTableHeader.UpdateStatus |= EFI_DEBUG_IMAGE_INFO_UPDATE_IN_PROGRESS; Table = mDebugInfoTableHeader.EfiDebugImageInfoTable; for (Index = 0; Index < mMaxTableEntries; Index++) { if (Table[Index].NormalImage != NULL && Table[Index].NormalImage->ImageHandle == ImageHandle) { // // Found a match. Free up the record, then NULL the pointer to indicate the slot // is free. // CoreFreePool (Table[Index].NormalImage); Table[Index].NormalImage = NULL; // // Decrease the number of EFI_DEBUG_IMAGE_INFO elements and set the mDebugInfoTable in modified status. // mDebugInfoTableHeader.TableSize--; mDebugInfoTableHeader.UpdateStatus |= EFI_DEBUG_IMAGE_INFO_TABLE_MODIFIED; break; } } mDebugInfoTableHeader.UpdateStatus &= ~EFI_DEBUG_IMAGE_INFO_UPDATE_IN_PROGRESS; }
/** Closes an event and frees the event structure. @param UserEvent Event to close @retval EFI_INVALID_PARAMETER Parameters are not valid. @retval EFI_SUCCESS The event has been closed **/ EFI_STATUS EFIAPI CoreCloseEvent ( IN EFI_EVENT UserEvent ) { EFI_STATUS Status; IEVENT *Event; Event = UserEvent; if (Event == NULL) { return EFI_INVALID_PARAMETER; } if (Event->Signature != EVENT_SIGNATURE) { return EFI_INVALID_PARAMETER; } // // If it's a timer event, make sure it's not pending // if ((Event->Type & EVT_TIMER) != 0) { CoreSetTimer (Event, TimerCancel, 0); } CoreAcquireEventLock (); // // If the event is queued somewhere, remove it // if (Event->RuntimeData.Link.ForwardLink != NULL) { RemoveEntryList (&Event->RuntimeData.Link); } if (Event->NotifyLink.ForwardLink != NULL) { RemoveEntryList (&Event->NotifyLink); } if (Event->SignalLink.ForwardLink != NULL) { RemoveEntryList (&Event->SignalLink); } CoreReleaseEventLock (); // // If the event is registered on a protocol notify, then remove it from the protocol database // CoreUnregisterProtocolNotify (Event); Status = CoreFreePool (Event); ASSERT_EFI_ERROR (Status); return Status; }
/** Given the supplied FW_VOL_BLOCK_PROTOCOL, allocate a buffer for output and copy the real length volume header into it. @param Fvb The FW_VOL_BLOCK_PROTOCOL instance from which to read the volume header @param FwVolHeader Pointer to pointer to allocated buffer in which the volume header is returned. @retval EFI_OUT_OF_RESOURCES No enough buffer could be allocated. @retval EFI_SUCCESS Successfully read volume header to the allocated buffer. **/ EFI_STATUS GetFwVolHeader ( IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb, OUT EFI_FIRMWARE_VOLUME_HEADER **FwVolHeader ) { EFI_STATUS Status; EFI_FIRMWARE_VOLUME_HEADER TempFvh; UINTN FvhLength; EFI_LBA StartLba; UINTN Offset; UINT8 *Buffer; // // Read the standard FV header // StartLba = 0; Offset = 0; FvhLength = sizeof (EFI_FIRMWARE_VOLUME_HEADER); Status = ReadFvbData (Fvb, &StartLba, &Offset, FvhLength, (UINT8 *)&TempFvh); if (EFI_ERROR (Status)) { return Status; } // // Allocate a buffer for the caller // *FwVolHeader = AllocatePool (TempFvh.HeaderLength); if (*FwVolHeader == NULL) { return EFI_OUT_OF_RESOURCES; } // // Copy the standard header into the buffer // CopyMem (*FwVolHeader, &TempFvh, sizeof (EFI_FIRMWARE_VOLUME_HEADER)); // // Read the rest of the header // FvhLength = TempFvh.HeaderLength - sizeof (EFI_FIRMWARE_VOLUME_HEADER); Buffer = (UINT8 *)*FwVolHeader + sizeof (EFI_FIRMWARE_VOLUME_HEADER); Status = ReadFvbData (Fvb, &StartLba, &Offset, FvhLength, Buffer); if (EFI_ERROR (Status)) { // // Read failed so free buffer // CoreFreePool (*FwVolHeader); } return Status; }
/** Removes an event from a register protocol notify list on a protocol. @param Event The event to search for in the protocol database. @return EFI_SUCCESS if the event was found and removed. @return EFI_NOT_FOUND if the event was not found in the protocl database. **/ EFI_STATUS CoreUnregisterProtocolNotifyEvent ( IN EFI_EVENT Event ) { LIST_ENTRY *Link; PROTOCOL_ENTRY *ProtEntry; LIST_ENTRY *NotifyLink; PROTOCOL_NOTIFY *ProtNotify; CoreAcquireProtocolLock (); for ( Link = mProtocolDatabase.ForwardLink; Link != &mProtocolDatabase; Link = Link->ForwardLink) { ProtEntry = CR(Link, PROTOCOL_ENTRY, AllEntries, PROTOCOL_ENTRY_SIGNATURE); for ( NotifyLink = ProtEntry->Notify.ForwardLink; NotifyLink != &ProtEntry->Notify; NotifyLink = NotifyLink->ForwardLink) { ProtNotify = CR(NotifyLink, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE); if (ProtNotify->Event == Event) { RemoveEntryList(&ProtNotify->Link); CoreFreePool(ProtNotify); CoreReleaseProtocolLock (); return EFI_SUCCESS; } } } CoreReleaseProtocolLock (); return EFI_NOT_FOUND; }
/** This notification function is invoked when an instance of the EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL is produced. It layers an instance of the EFI_FIRMWARE_VOLUME2_PROTOCOL on the same handle. This is the function where the actual initialization of the EFI_FIRMWARE_VOLUME2_PROTOCOL is done. @param Event The event that occured @param Context For EFI compatiblity. Not used. **/ VOID EFIAPI NotifyFwVolBlock ( IN EFI_EVENT Event, IN VOID *Context ) { EFI_HANDLE Handle; EFI_STATUS Status; UINTN BufferSize; EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb; EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv; FV_DEVICE *FvDevice; EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; // // Examine all new handles // for (;;) { // // Get the next handle // BufferSize = sizeof (Handle); Status = CoreLocateHandle ( ByRegisterNotify, NULL, gEfiFwVolBlockNotifyReg, &BufferSize, &Handle ); // // If not found, we're done // if (EFI_NOT_FOUND == Status) { break; } if (EFI_ERROR (Status)) { continue; } // // Get the FirmwareVolumeBlock protocol on that handle // Status = CoreHandleProtocol (Handle, &gEfiFirmwareVolumeBlockProtocolGuid, (VOID **)&Fvb); ASSERT_EFI_ERROR (Status); ASSERT (Fvb != NULL); // // Make sure the Fv Header is O.K. // Status = GetFwVolHeader (Fvb, &FwVolHeader); if (EFI_ERROR (Status)) { return; } ASSERT (FwVolHeader != NULL); if (!VerifyFvHeaderChecksum (FwVolHeader)) { CoreFreePool (FwVolHeader); continue; } // // Check to see that the file system is indeed formatted in a way we can // understand it... // if ((!CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiFirmwareFileSystem2Guid)) && (!CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiFirmwareFileSystem3Guid))) { continue; } // // Check if there is an FV protocol already installed in that handle // Status = CoreHandleProtocol (Handle, &gEfiFirmwareVolume2ProtocolGuid, (VOID **)&Fv); if (!EFI_ERROR (Status)) { // // Update Fv to use a new Fvb // FvDevice = BASE_CR (Fv, FV_DEVICE, Fv); if (FvDevice->Signature == FV2_DEVICE_SIGNATURE) { // // Only write into our device structure if it's our device structure // FvDevice->Fvb = Fvb; } } else { // // No FwVol protocol on the handle so create a new one // FvDevice = AllocateCopyPool (sizeof (FV_DEVICE), &mFvDevice); if (FvDevice == NULL) { return; } FvDevice->Fvb = Fvb; FvDevice->Handle = Handle; FvDevice->FwVolHeader = FwVolHeader; FvDevice->IsFfs3Fv = CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiFirmwareFileSystem3Guid); FvDevice->Fv.ParentHandle = Fvb->ParentHandle; if (Fvb->ParentHandle != NULL) { // // Inherit the authentication status from FVB. // FvDevice->AuthenticationStatus = GetFvbAuthenticationStatus (Fvb); } if (!EFI_ERROR (FvCheck (FvDevice))) { // // Install an New FV protocol on the existing handle // Status = CoreInstallProtocolInterface ( &Handle, &gEfiFirmwareVolume2ProtocolGuid, EFI_NATIVE_INTERFACE, &FvDevice->Fv ); ASSERT_EFI_ERROR (Status); } else { // // Free FvDevice Buffer for the corrupt FV image. // CoreFreePool (FvDevice); } } } return; }
/** Check if an FV is consistent and allocate cache for it. @param FvDevice A pointer to the FvDevice to be checked. @retval EFI_OUT_OF_RESOURCES No enough buffer could be allocated. @retval EFI_SUCCESS FV is consistent and cache is allocated. @retval EFI_VOLUME_CORRUPTED File system is corrupted. **/ EFI_STATUS FvCheck ( IN OUT FV_DEVICE *FvDevice ) { EFI_STATUS Status; EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb; EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; EFI_FIRMWARE_VOLUME_EXT_HEADER *FwVolExtHeader; EFI_FVB_ATTRIBUTES_2 FvbAttributes; EFI_FV_BLOCK_MAP_ENTRY *BlockMap; FFS_FILE_LIST_ENTRY *FfsFileEntry; EFI_FFS_FILE_HEADER *FfsHeader; UINT8 *CacheLocation; UINTN LbaOffset; UINTN HeaderSize; UINTN Index; EFI_LBA LbaIndex; UINTN Size; EFI_FFS_FILE_STATE FileState; UINT8 *TopFvAddress; UINTN TestLength; EFI_PHYSICAL_ADDRESS PhysicalAddress; BOOLEAN FileCached; UINTN WholeFileSize; EFI_FFS_FILE_HEADER *CacheFfsHeader; FileCached = FALSE; CacheFfsHeader = NULL; Fvb = FvDevice->Fvb; FwVolHeader = FvDevice->FwVolHeader; Status = Fvb->GetAttributes (Fvb, &FvbAttributes); if (EFI_ERROR (Status)) { return Status; } // // Size is the size of the FV minus the head. We have already allocated // the header to check to make sure the volume is valid // Size = (UINTN)(FwVolHeader->FvLength - FwVolHeader->HeaderLength); if ((FvbAttributes & EFI_FVB2_MEMORY_MAPPED) != 0) { FvDevice->IsMemoryMapped = TRUE; Status = Fvb->GetPhysicalAddress (Fvb, &PhysicalAddress); if (EFI_ERROR (Status)) { return Status; } // // Don't cache memory mapped FV really. // FvDevice->CachedFv = (UINT8 *) (UINTN) (PhysicalAddress + FwVolHeader->HeaderLength); } else { FvDevice->IsMemoryMapped = FALSE; FvDevice->CachedFv = AllocatePool (Size); if (FvDevice->CachedFv == NULL) { return EFI_OUT_OF_RESOURCES; } } // // Remember a pointer to the end fo the CachedFv // FvDevice->EndOfCachedFv = FvDevice->CachedFv + Size; if (!FvDevice->IsMemoryMapped) { // // Copy FV minus header into memory using the block map we have all ready // read into memory. // BlockMap = FwVolHeader->BlockMap; CacheLocation = FvDevice->CachedFv; LbaIndex = 0; LbaOffset = 0; HeaderSize = FwVolHeader->HeaderLength; while ((BlockMap->NumBlocks != 0) || (BlockMap->Length != 0)) { Index = 0; Size = BlockMap->Length; if (HeaderSize > 0) { // // Skip header size // for (; Index < BlockMap->NumBlocks && HeaderSize >= BlockMap->Length; Index ++) { HeaderSize -= BlockMap->Length; LbaIndex ++; } // // Check whether FvHeader is crossing the multi block range. // if (Index >= BlockMap->NumBlocks) { BlockMap++; continue; } else if (HeaderSize > 0) { LbaOffset = HeaderSize; Size = BlockMap->Length - HeaderSize; HeaderSize = 0; } } // // read the FV data // for (; Index < BlockMap->NumBlocks; Index ++) { Status = Fvb->Read (Fvb, LbaIndex, LbaOffset, &Size, CacheLocation ); // // Not check EFI_BAD_BUFFER_SIZE, for Size = BlockMap->Length // if (EFI_ERROR (Status)) { goto Done; } LbaIndex++; CacheLocation += Size; // // After we skip Fv Header always read from start of block // LbaOffset = 0; Size = BlockMap->Length; } BlockMap++; } } // // Scan to check the free space & File list // if ((FvbAttributes & EFI_FVB2_ERASE_POLARITY) != 0) { FvDevice->ErasePolarity = 1; } else { FvDevice->ErasePolarity = 0; } // // go through the whole FV cache, check the consistence of the FV. // Make a linked list of all the Ffs file headers // Status = EFI_SUCCESS; InitializeListHead (&FvDevice->FfsFileListHeader); // // Build FFS list // if (FwVolHeader->ExtHeaderOffset != 0) { // // Searching for files starts on an 8 byte aligned boundary after the end of the Extended Header if it exists. // FwVolExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *) (FvDevice->CachedFv + (FwVolHeader->ExtHeaderOffset - FwVolHeader->HeaderLength)); FfsHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FwVolExtHeader + FwVolExtHeader->ExtHeaderSize); FfsHeader = (EFI_FFS_FILE_HEADER *) ALIGN_POINTER (FfsHeader, 8); } else { FfsHeader = (EFI_FFS_FILE_HEADER *) (FvDevice->CachedFv); } TopFvAddress = FvDevice->EndOfCachedFv; while (((UINTN) FfsHeader >= (UINTN) FvDevice->CachedFv) && ((UINTN) FfsHeader <= (UINTN) ((UINTN) TopFvAddress - sizeof (EFI_FFS_FILE_HEADER)))) { if (FileCached) { CoreFreePool (CacheFfsHeader); FileCached = FALSE; } TestLength = TopFvAddress - ((UINT8 *) FfsHeader); if (TestLength > sizeof (EFI_FFS_FILE_HEADER)) { TestLength = sizeof (EFI_FFS_FILE_HEADER); } if (IsBufferErased (FvDevice->ErasePolarity, FfsHeader, TestLength)) { // // We have found the free space so we are done! // goto Done; } if (!IsValidFfsHeader (FvDevice->ErasePolarity, FfsHeader, &FileState)) { if ((FileState == EFI_FILE_HEADER_INVALID) || (FileState == EFI_FILE_HEADER_CONSTRUCTION)) { if (IS_FFS_FILE2 (FfsHeader)) { if (!FvDevice->IsFfs3Fv) { DEBUG ((EFI_D_ERROR, "Found a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &FfsHeader->Name)); } FfsHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsHeader + sizeof (EFI_FFS_FILE_HEADER2)); } else { FfsHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsHeader + sizeof (EFI_FFS_FILE_HEADER)); } continue; } else { // // File system is corrputed // Status = EFI_VOLUME_CORRUPTED; goto Done; } } CacheFfsHeader = FfsHeader; if ((CacheFfsHeader->Attributes & FFS_ATTRIB_CHECKSUM) == FFS_ATTRIB_CHECKSUM) { if (FvDevice->IsMemoryMapped) { // // Memory mapped FV has not been cached. // Here is to cache FFS file to memory buffer for following checksum calculating. // And then, the cached file buffer can be also used for FvReadFile. // WholeFileSize = IS_FFS_FILE2 (CacheFfsHeader) ? FFS_FILE2_SIZE (CacheFfsHeader): FFS_FILE_SIZE (CacheFfsHeader); CacheFfsHeader = AllocateCopyPool (WholeFileSize, CacheFfsHeader); if (CacheFfsHeader == NULL) { Status = EFI_OUT_OF_RESOURCES; goto Done; } FileCached = TRUE; } } if (!IsValidFfsFile (FvDevice->ErasePolarity, CacheFfsHeader)) { // // File system is corrupted // Status = EFI_VOLUME_CORRUPTED; goto Done; } if (IS_FFS_FILE2 (CacheFfsHeader)) { ASSERT (FFS_FILE2_SIZE (CacheFfsHeader) > 0x00FFFFFF); if (!FvDevice->IsFfs3Fv) { DEBUG ((EFI_D_ERROR, "Found a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &CacheFfsHeader->Name)); FfsHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsHeader + FFS_FILE2_SIZE (CacheFfsHeader)); // // Adjust pointer to the next 8-byte aligned boundry. // FfsHeader = (EFI_FFS_FILE_HEADER *) (((UINTN) FfsHeader + 7) & ~0x07); continue; } } FileState = GetFileState (FvDevice->ErasePolarity, CacheFfsHeader); // // check for non-deleted file // if (FileState != EFI_FILE_DELETED) { // // Create a FFS list entry for each non-deleted file // FfsFileEntry = AllocateZeroPool (sizeof (FFS_FILE_LIST_ENTRY)); if (FfsFileEntry == NULL) { Status = EFI_OUT_OF_RESOURCES; goto Done; } FfsFileEntry->FfsHeader = CacheFfsHeader; FfsFileEntry->FileCached = FileCached; FileCached = FALSE; InsertTailList (&FvDevice->FfsFileListHeader, &FfsFileEntry->Link); } if (IS_FFS_FILE2 (CacheFfsHeader)) { FfsHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsHeader + FFS_FILE2_SIZE (CacheFfsHeader)); } else { FfsHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsHeader + FFS_FILE_SIZE (CacheFfsHeader)); } // // Adjust pointer to the next 8-byte aligned boundry. // FfsHeader = (EFI_FFS_FILE_HEADER *)(((UINTN)FfsHeader + 7) & ~0x07); } Done: if (EFI_ERROR (Status)) { if (FileCached) { CoreFreePool (CacheFfsHeader); FileCached = FALSE; } FreeFvDeviceResource (FvDevice); } return Status; }
EFI_BOOTSERVICE EFI_STATUS EFIAPI CoreInstallConfigurationTable ( IN EFI_GUID *Guid, IN VOID *Table ) /*++ Routine Description: Boot Service called to add, modify, or remove a system configuration table from the EFI System Table. Arguments: Guid - Pointer to the GUID for the entry to add, update, or remove Table - Pointer to the configuration table for the entry to add, update, or remove, may be NULL. Returns: EFI_SUCCESS Guid, Table pair added, updated, or removed. EFI_INVALID_PARAMETER Input GUID not valid. EFI_NOT_FOUND Attempted to delete non-existant entry EFI_OUT_OF_RESOURCES Not enough memory available --*/ { UINTN Index; EFI_CONFIGURATION_TABLE *EfiConfigurationTable; // // If Guid is NULL, then this operation cannot be performed // if (Guid == NULL) { return EFI_INVALID_PARAMETER; } EfiConfigurationTable = gST->ConfigurationTable; // // Search all the table for an entry that matches Guid // for (Index = 0; Index < gST->NumberOfTableEntries; Index++) { if (EfiCompareGuid (Guid, &(gST->ConfigurationTable[Index].VendorGuid))) { break; } } if (Index < gST->NumberOfTableEntries) { // // A match was found, so this is either a modify or a delete operation // if (Table != NULL) { // // If Table is not NULL, then this is a modify operation. // Modify the table enty and return. // gST->ConfigurationTable[Index].VendorTable = Table; #if (EFI_SPECIFICATION_VERSION >= 0x0002000A) // // Signal Configuration Table change // CoreNotifySignalList (Guid); #endif return EFI_SUCCESS; } // // A match was found and Table is NULL, so this is a delete operation. // gST->NumberOfTableEntries--; // // Copy over deleted entry // EfiCommonLibCopyMem ( &(EfiConfigurationTable[Index]), &(gST->ConfigurationTable[Index + 1]), (gST->NumberOfTableEntries - Index) * sizeof (EFI_CONFIGURATION_TABLE) ); } else { // // No matching GUIDs were found, so this is an add operation. // if (Table == NULL) { // // If Table is NULL on an add operation, then return an error. // return EFI_NOT_FOUND; } // // Assume that Index == gST->NumberOfTableEntries // if ((Index * sizeof (EFI_CONFIGURATION_TABLE)) >= mSystemTableAllocateSize) { // // Allocate a table with one additional entry. // mSystemTableAllocateSize += (CONFIG_TABLE_SIZE_INCREASED * sizeof (EFI_CONFIGURATION_TABLE)); EfiConfigurationTable = CoreAllocateRuntimePool (mSystemTableAllocateSize); if (EfiConfigurationTable == NULL) { // // If a new table could not be allocated, then return an error. // return EFI_OUT_OF_RESOURCES; } if (gST->ConfigurationTable != NULL) { // // Copy the old table to the new table. // EfiCommonLibCopyMem ( EfiConfigurationTable, gST->ConfigurationTable, Index * sizeof (EFI_CONFIGURATION_TABLE) ); // // Free Old Table // CoreFreePool (gST->ConfigurationTable); } // // Update System Table // gST->ConfigurationTable = EfiConfigurationTable; } // // Fill in the new entry // EfiConfigurationTable[Index].VendorGuid = *Guid; EfiConfigurationTable[Index].VendorTable = Table; // // This is an add operation, so increment the number of table entries // gST->NumberOfTableEntries++; } // // Fix up the CRC-32 in the EFI System Table // CalculateEfiHdrCrc (&gST->Hdr); #if (EFI_SPECIFICATION_VERSION >= 0x0002000A) // // Signal Configuration Table change // CoreNotifySignalList (Guid); #endif return EFI_SUCCESS; }
/** Adds a new DebugImageInfo structure to the DebugImageInfo Table. Re-Allocates the table if it's not large enough to accomidate another entry. @param ImageInfoType type of debug image information @param LoadedImage pointer to the loaded image protocol for the image being loaded @param ImageHandle image handle for the image being loaded **/ VOID CoreNewDebugImageInfoEntry ( IN UINT32 ImageInfoType, IN EFI_LOADED_IMAGE_PROTOCOL *LoadedImage, IN EFI_HANDLE ImageHandle ) { EFI_DEBUG_IMAGE_INFO *Table; EFI_DEBUG_IMAGE_INFO *NewTable; UINTN Index; UINTN TableSize; // // Set the flag indicating that we're in the process of updating the table. // mDebugInfoTableHeader.UpdateStatus |= EFI_DEBUG_IMAGE_INFO_UPDATE_IN_PROGRESS; Table = mDebugInfoTableHeader.EfiDebugImageInfoTable; if (mDebugInfoTableHeader.TableSize < mMaxTableEntries) { // // We still have empty entires in the Table, find the first empty entry. // Index = 0; while (Table[Index].NormalImage != NULL) { Index++; } // // There must be an empty entry in the in the table. // ASSERT (Index < mMaxTableEntries); } else { // // Table is full, so re-allocate another page for a larger table... // TableSize = mMaxTableEntries * EFI_DEBUG_TABLE_ENTRY_SIZE; NewTable = AllocateZeroPool (TableSize + EFI_PAGE_SIZE); if (NewTable == NULL) { mDebugInfoTableHeader.UpdateStatus &= ~EFI_DEBUG_IMAGE_INFO_UPDATE_IN_PROGRESS; return; } // // Copy the old table into the new one // CopyMem (NewTable, Table, TableSize); // // Free the old table // CoreFreePool (Table); // // Update the table header // Table = NewTable; mDebugInfoTableHeader.EfiDebugImageInfoTable = NewTable; // // Enlarge the max table entries and set the first empty entry index to // be the original max table entries. // Index = mMaxTableEntries; mMaxTableEntries += EFI_PAGE_SIZE / EFI_DEBUG_TABLE_ENTRY_SIZE; } // // Allocate data for new entry // Table[Index].NormalImage = AllocateZeroPool (sizeof (EFI_DEBUG_IMAGE_INFO_NORMAL)); if (Table[Index].NormalImage != NULL) { // // Update the entry // Table[Index].NormalImage->ImageInfoType = (UINT32) ImageInfoType; Table[Index].NormalImage->LoadedImageProtocolInstance = LoadedImage; Table[Index].NormalImage->ImageHandle = ImageHandle; // // Increase the number of EFI_DEBUG_IMAGE_INFO elements and set the mDebugInfoTable in modified status. // mDebugInfoTableHeader.TableSize++; mDebugInfoTableHeader.UpdateStatus |= EFI_DEBUG_IMAGE_INFO_TABLE_MODIFIED; } mDebugInfoTableHeader.UpdateStatus &= ~EFI_DEBUG_IMAGE_INFO_UPDATE_IN_PROGRESS; }
EFI_BOOTSERVICE EFI_STATUS EFIAPI CoreCloseEvent ( IN EFI_EVENT UserEvent ) /*++ Routine Description: Closes an event and frees the event structure. Arguments: UserEvent - Event to close Returns: EFI_INVALID_PARAMETER - Parameters are not valid. EFI_SUCCESS - The event has been closed --*/ { EFI_STATUS Status; IEVENT *Event; Event = UserEvent; if (Event == NULL) { return EFI_INVALID_PARAMETER; } if (Event->Signature != EVENT_SIGNATURE) { return EFI_INVALID_PARAMETER; } // // If it's a timer event, make sure it's not pending // if (Event->Type & EFI_EVENT_TIMER) { CoreSetTimer (Event, TimerCancel, 0); } CoreAcquireEventLock (); // // If the event is queued somewhere, remove it // if (Event->RuntimeData.Link.ForwardLink != NULL) { RemoveEntryList (&Event->RuntimeData.Link); } if (Event->NotifyLink.ForwardLink != NULL) { RemoveEntryList (&Event->NotifyLink); } if (Event->SignalLink.ForwardLink != NULL) { RemoveEntryList (&Event->SignalLink); } CoreReleaseEventLock (); // // If the event is registered on a protocol notify, // then remove it from the protocol database // CoreUnregisterProtocolNotify (Event); Status = CoreFreePool (Event); ASSERT_EFI_ERROR (Status); return Status; }
/** Uninstalls all instances of a protocol:interfacer from a handle. If the last protocol interface is remove from the handle, the handle is freed. @param UserHandle The handle to remove the protocol handler from @param Protocol The protocol, of protocol:interface, to remove @param Interface The interface, of protocol:interface, to remove @retval EFI_INVALID_PARAMETER Protocol is NULL. @retval EFI_SUCCESS Protocol interface successfully uninstalled. **/ EFI_STATUS EFIAPI CoreUninstallProtocolInterface ( IN EFI_HANDLE UserHandle, IN EFI_GUID *Protocol, IN VOID *Interface ) { EFI_STATUS Status; IHANDLE *Handle; PROTOCOL_INTERFACE *Prot; // // Check that Protocol is valid // if (Protocol == NULL) { return EFI_INVALID_PARAMETER; } // // Check that UserHandle is a valid handle // Status = CoreValidateHandle (UserHandle); if (EFI_ERROR (Status)) { return Status; } // // Lock the protocol database // CoreAcquireProtocolLock (); // // Check that Protocol exists on UserHandle, and Interface matches the interface in the database // Prot = CoreFindProtocolInterface (UserHandle, Protocol, Interface); if (Prot == NULL) { Status = EFI_NOT_FOUND; goto Done; } // // Attempt to disconnect all drivers that are using the protocol interface that is about to be removed // Status = CoreDisconnectControllersUsingProtocolInterface ( UserHandle, Prot ); if (EFI_ERROR (Status)) { // // One or more drivers refused to release, so return the error // goto Done; } // // Remove the protocol interface from the protocol // Status = EFI_NOT_FOUND; Handle = (IHANDLE *)UserHandle; Prot = CoreRemoveInterfaceFromProtocol (Handle, Protocol, Interface); if (Prot != NULL) { // // Update the Key to show that the handle has been created/modified // gHandleDatabaseKey++; Handle->Key = gHandleDatabaseKey; // // Remove the protocol interface from the handle // RemoveEntryList (&Prot->Link); // // Free the memory // Prot->Signature = 0; CoreFreePool (Prot); Status = EFI_SUCCESS; } // // If there are no more handlers for the handle, free the handle // if (IsListEmpty (&Handle->Protocols)) { Handle->Signature = 0; RemoveEntryList (&Handle->AllHandles); CoreFreePool (Handle); } Done: // // Done, unlock the database and return // CoreReleaseProtocolLock (); return Status; }
/** Attempts to disconnect all drivers that are using the protocol interface being queried. If failed, reconnect all drivers disconnected. Note: This function doesn't do parameters checking, it's caller's responsibility to pass in valid parameters. @param UserHandle The handle on which the protocol is installed @param Prot The protocol to disconnect drivers from @retval EFI_SUCCESS Drivers using the protocol interface are all disconnected @retval EFI_ACCESS_DENIED Failed to disconnect one or all of the drivers **/ EFI_STATUS CoreDisconnectControllersUsingProtocolInterface ( IN EFI_HANDLE UserHandle, IN PROTOCOL_INTERFACE *Prot ) { EFI_STATUS Status; BOOLEAN ItemFound; LIST_ENTRY *Link; OPEN_PROTOCOL_DATA *OpenData; Status = EFI_SUCCESS; // // Attempt to disconnect all drivers from this protocol interface // do { ItemFound = FALSE; for (Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList; Link = Link->ForwardLink) { OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE); if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) { CoreReleaseProtocolLock (); Status = CoreDisconnectController (UserHandle, OpenData->AgentHandle, NULL); CoreAcquireProtocolLock (); if (!EFI_ERROR (Status)) { ItemFound = TRUE; } break; } } } while (ItemFound); if (!EFI_ERROR (Status)) { // // Attempt to remove BY_HANDLE_PROTOOCL and GET_PROTOCOL and TEST_PROTOCOL Open List items // for (Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList;) { OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE); if ((OpenData->Attributes & (EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL | EFI_OPEN_PROTOCOL_GET_PROTOCOL | EFI_OPEN_PROTOCOL_TEST_PROTOCOL)) != 0) { Link = RemoveEntryList (&OpenData->Link); Prot->OpenListCount--; CoreFreePool (OpenData); } else { Link = Link->ForwardLink; } } } // // If there are errors or still has open items in the list, then reconnect all the drivers and return an error // if (EFI_ERROR (Status) || (Prot->OpenListCount > 0)) { CoreReleaseProtocolLock (); CoreConnectController (UserHandle, NULL, NULL, TRUE); CoreAcquireProtocolLock (); Status = EFI_ACCESS_DENIED; } return Status; }
/** Installs a protocol interface into the boot services environment. @param UserHandle The handle to install the protocol handler on, or NULL if a new handle is to be allocated @param Protocol The protocol to add to the handle @param InterfaceType Indicates whether Interface is supplied in native form. @param Interface The interface for the protocol being added @param Notify indicates whether notify the notification list for this protocol @retval EFI_INVALID_PARAMETER Invalid parameter @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate @retval EFI_SUCCESS Protocol interface successfully installed **/ EFI_STATUS CoreInstallProtocolInterfaceNotify ( IN OUT EFI_HANDLE *UserHandle, IN EFI_GUID *Protocol, IN EFI_INTERFACE_TYPE InterfaceType, IN VOID *Interface, IN BOOLEAN Notify ) { PROTOCOL_INTERFACE *Prot; PROTOCOL_ENTRY *ProtEntry; IHANDLE *Handle; EFI_STATUS Status; VOID *ExistingInterface; // // returns EFI_INVALID_PARAMETER if InterfaceType is invalid. // Also added check for invalid UserHandle and Protocol pointers. // if (UserHandle == NULL || Protocol == NULL) { return EFI_INVALID_PARAMETER; } if (InterfaceType != EFI_NATIVE_INTERFACE) { return EFI_INVALID_PARAMETER; } // // Print debug message // DEBUG((DEBUG_INFO, "InstallProtocolInterface: %g %p\n", Protocol, Interface)); Status = EFI_OUT_OF_RESOURCES; Prot = NULL; Handle = NULL; if (*UserHandle != NULL) { Status = CoreHandleProtocol (*UserHandle, Protocol, (VOID **)&ExistingInterface); if (!EFI_ERROR (Status)) { return EFI_INVALID_PARAMETER; } } // // Lock the protocol database // CoreAcquireProtocolLock (); // // Lookup the Protocol Entry for the requested protocol // ProtEntry = CoreFindProtocolEntry (Protocol, TRUE); if (ProtEntry == NULL) { goto Done; } // // Allocate a new protocol interface structure // Prot = AllocateZeroPool (sizeof(PROTOCOL_INTERFACE)); if (Prot == NULL) { Status = EFI_OUT_OF_RESOURCES; goto Done; } // // If caller didn't supply a handle, allocate a new one // Handle = (IHANDLE *)*UserHandle; if (Handle == NULL) { Handle = AllocateZeroPool (sizeof(IHANDLE)); if (Handle == NULL) { Status = EFI_OUT_OF_RESOURCES; goto Done; } // // Initialize new handler structure // Handle->Signature = EFI_HANDLE_SIGNATURE; InitializeListHead (&Handle->Protocols); // // Initialize the Key to show that the handle has been created/modified // gHandleDatabaseKey++; Handle->Key = gHandleDatabaseKey; // // Add this handle to the list global list of all handles // in the system // InsertTailList (&gHandleList, &Handle->AllHandles); } else { Status = CoreValidateHandle (Handle); if (EFI_ERROR (Status)) { DEBUG((DEBUG_ERROR, "InstallProtocolInterface: input handle at 0x%x is invalid\n", Handle)); goto Done; } } // // Each interface that is added must be unique // ASSERT (CoreFindProtocolInterface (Handle, Protocol, Interface) == NULL); // // Initialize the protocol interface structure // Prot->Signature = PROTOCOL_INTERFACE_SIGNATURE; Prot->Handle = Handle; Prot->Protocol = ProtEntry; Prot->Interface = Interface; // // Initalize OpenProtocol Data base // InitializeListHead (&Prot->OpenList); Prot->OpenListCount = 0; // // Add this protocol interface to the head of the supported // protocol list for this handle // InsertHeadList (&Handle->Protocols, &Prot->Link); // // Add this protocol interface to the tail of the // protocol entry // InsertTailList (&ProtEntry->Protocols, &Prot->ByProtocol); // // Notify the notification list for this protocol // if (Notify) { CoreNotifyProtocolEntry (ProtEntry); } Status = EFI_SUCCESS; Done: // // Done, unlock the database and return // CoreReleaseProtocolLock (); if (!EFI_ERROR (Status)) { // // Return the new handle back to the caller // *UserHandle = Handle; } else { // // There was an error, clean up // if (Prot != NULL) { CoreFreePool (Prot); } DEBUG((DEBUG_ERROR, "InstallProtocolInterface: %g %p failed with %r\n", Protocol, Interface, Status)); } return Status; }