| /*++ | |
| Copyright (c) 2006 - 2007, Intel Corporation | |
| All rights reserved. This program and the accompanying materials | |
| are licensed and made available under the terms and conditions of the BSD License | |
| which accompanies this distribution. The full text of the license may be found at | |
| http://opensource.org/licenses/bsd-license.php | |
| THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, | |
| WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. | |
| Module Name: | |
| DebugImageInfo.c | |
| Abstract: | |
| Support functions for managing debug image info table when loading and unloading | |
| images. | |
| --*/ | |
| #include <DxeMain.h> | |
| static EFI_DEBUG_IMAGE_INFO_TABLE_HEADER mDebugInfoTableHeader = { | |
| 0, // volatile UINT32 UpdateStatus; | |
| 0, // UINT32 TableSize; | |
| NULL // EFI_DEBUG_IMAGE_INFO *EfiDebugImageInfoTable; | |
| }; | |
| static EFI_SYSTEM_TABLE_POINTER *mDebugTable = NULL; | |
| VOID | |
| CoreInitializeDebugImageInfoTable ( | |
| VOID | |
| ) | |
| /*++ | |
| Routine Description: | |
| Creates and initializes the DebugImageInfo Table. Also creates the configuration | |
| table and registers it into the system table. | |
| Arguments: | |
| None | |
| Returns: | |
| NA | |
| Notes: | |
| This function allocates memory, frees it, and then allocates memory at an | |
| address within the initial allocation. Since this function is called early | |
| in DXE core initialization (before drivers are dispatched), this should not | |
| be a problem. | |
| --*/ | |
| { | |
| EFI_STATUS Status; | |
| EFI_PHYSICAL_ADDRESS Mem; | |
| UINTN NumberOfPages; | |
| // | |
| // Allocate boot services memory for the structure. It's required to be aligned on | |
| // a 4M boundary, so allocate a 4M block (plus what we require), free it up, calculate | |
| // a 4M aligned address within the memory we just freed, and then allocate memory at that | |
| // address for our initial structure. | |
| // | |
| NumberOfPages = FOUR_MEG_PAGES + EFI_SIZE_TO_PAGES(sizeof (EFI_SYSTEM_TABLE_POINTER)); | |
| Status = CoreAllocatePages (AllocateAnyPages, EfiBootServicesData, NumberOfPages , &Mem); | |
| ASSERT_EFI_ERROR (Status); | |
| if (EFI_ERROR(Status)) { | |
| return; | |
| } | |
| Status = CoreFreePages (Mem, NumberOfPages); | |
| ASSERT_EFI_ERROR (Status); | |
| if (EFI_ERROR(Status)) { | |
| return; | |
| } | |
| // | |
| // Now get a 4M aligned address within the memory range we were given. | |
| // Then allocate memory at that address | |
| // | |
| Mem = (Mem + FOUR_MEG_MASK) & (~FOUR_MEG_MASK); | |
| Status = CoreAllocatePages (AllocateAddress, EfiBootServicesData, NumberOfPages - FOUR_MEG_PAGES, &Mem); | |
| ASSERT_EFI_ERROR (Status); | |
| if (EFI_ERROR(Status)) { | |
| return; | |
| } | |
| // | |
| // We now have a 4M aligned page allocated, so fill in the data structure. | |
| // Ideally we would update the CRC now as well, but the service may not yet be available. | |
| // See comments in the CoreUpdateDebugTableCrc32() function below for details. | |
| // | |
| mDebugTable = (EFI_SYSTEM_TABLE_POINTER *)(UINTN)Mem; | |
| mDebugTable->Signature = EFI_SYSTEM_TABLE_SIGNATURE; | |
| mDebugTable->EfiSystemTableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) gDxeCoreST; | |
| mDebugTable->Crc32 = 0; | |
| Status = CoreInstallConfigurationTable (&gEfiDebugImageInfoTableGuid, &mDebugInfoTableHeader); | |
| ASSERT_EFI_ERROR (Status); | |
| } | |
| VOID | |
| CoreUpdateDebugTableCrc32 ( | |
| VOID | |
| ) | |
| /*++ | |
| Routine Description: | |
| Update the CRC32 in the Debug Table. | |
| Since the CRC32 service is made available by the Runtime driver, we have to | |
| wait for the Runtime Driver to be installed before the CRC32 can be computed. | |
| This function is called elsewhere by the core when the runtime architectural | |
| protocol is produced. | |
| Arguments: | |
| None | |
| Returns: | |
| NA | |
| --*/ | |
| { | |
| ASSERT(mDebugTable != NULL); | |
| mDebugTable->Crc32 = 0; | |
| gDxeCoreBS->CalculateCrc32 ((VOID *)mDebugTable, sizeof (EFI_SYSTEM_TABLE_POINTER), &mDebugTable->Crc32); | |
| } | |
| VOID | |
| CoreNewDebugImageInfoEntry ( | |
| IN UINT32 ImageInfoType, | |
| IN EFI_LOADED_IMAGE_PROTOCOL *LoadedImage, | |
| IN EFI_HANDLE ImageHandle | |
| ) | |
| /*++ | |
| Routine Description: | |
| Adds a new DebugImageInfo structure to the DebugImageInfo Table. Re-Allocates | |
| the table if it's not large enough to accomidate another entry. | |
| Arguments: | |
| ImageInfoType - type of debug image information | |
| LoadedImage - pointer to the loaded image protocol for the image being loaded | |
| ImageHandle - image handle for the image being loaded | |
| Returns: | |
| NA | |
| --*/ | |
| { | |
| EFI_DEBUG_IMAGE_INFO *Table; | |
| EFI_DEBUG_IMAGE_INFO *NewTable; | |
| UINTN Index; | |
| UINTN MaxTableIndex; | |
| 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; | |
| MaxTableIndex = mDebugInfoTableHeader.TableSize; | |
| for (Index = 0; Index < MaxTableIndex; Index++) { | |
| if (Table[Index].NormalImage == NULL) { | |
| // | |
| // We have found a free entry so exit the loop | |
| // | |
| break; | |
| } | |
| } | |
| if (Index == MaxTableIndex) { | |
| // | |
| // Table is full, so re-allocate another page for a larger table... | |
| // | |
| TableSize = MaxTableIndex * EFI_DEBUG_TABLE_ENTRY_SIZE; | |
| NewTable = CoreAllocateZeroBootServicesPool (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; | |
| mDebugInfoTableHeader.TableSize += EFI_PAGE_SIZE / EFI_DEBUG_TABLE_ENTRY_SIZE; | |
| } | |
| // | |
| // Allocate data for new entry | |
| // | |
| Table[Index].NormalImage = CoreAllocateZeroBootServicesPool (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; | |
| } | |
| mDebugInfoTableHeader.UpdateStatus &= ~EFI_DEBUG_IMAGE_INFO_UPDATE_IN_PROGRESS; | |
| } | |
| VOID | |
| CoreRemoveDebugImageInfoEntry ( | |
| EFI_HANDLE ImageHandle | |
| ) | |
| /*++ | |
| Routine Description: | |
| Removes and frees an entry from the DebugImageInfo Table. | |
| Arguments: | |
| ImageHandle - image handle for the image being unloaded | |
| Returns: | |
| NA | |
| --*/ | |
| { | |
| EFI_DEBUG_IMAGE_INFO *Table; | |
| UINTN Index; | |
| mDebugInfoTableHeader.UpdateStatus |= EFI_DEBUG_IMAGE_INFO_UPDATE_IN_PROGRESS; | |
| Table = mDebugInfoTableHeader.EfiDebugImageInfoTable; | |
| for (Index = 0; Index < mDebugInfoTableHeader.TableSize; 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; | |
| break; | |
| } | |
| } | |
| mDebugInfoTableHeader.UpdateStatus &= ~EFI_DEBUG_IMAGE_INFO_UPDATE_IN_PROGRESS; | |
| } | |