EDK2 doxygen online documents - Firmware Encoding Index 1
EDK2 doxygen online documents - Firmware Encoding Index

MdeModulePkg/Core/PiSmmCore/Dispatcher.c

Go to the documentation of this file.
00001 
00041 #include "PiSmmCore.h"
00042 
00043 //
00044 // SMM Dispatcher Data structures
00045 //
00046 #define KNOWN_HANDLE_SIGNATURE  SIGNATURE_32('k','n','o','w')
00047 typedef struct {
00048   UINTN           Signature;
00049   LIST_ENTRY      Link;         // mFvHandleList
00050   EFI_HANDLE      Handle;
00051 } KNOWN_HANDLE;
00052 
00053 //
00054 // Function Prototypes
00055 //
00056 
00068 VOID
00069 SmmInsertOnScheduledQueueWhileProcessingBeforeAndAfter (
00070   IN  EFI_SMM_DRIVER_ENTRY   *InsertedDriverEntry
00071   );
00072 
00073 //
00074 // The Driver List contains one copy of every driver that has been discovered.
00075 // Items are never removed from the driver list. List of EFI_SMM_DRIVER_ENTRY
00076 //
00077 LIST_ENTRY  mDiscoveredList = INITIALIZE_LIST_HEAD_VARIABLE (mDiscoveredList);
00078 
00079 //
00080 // Queue of drivers that are ready to dispatch. This queue is a subset of the
00081 // mDiscoveredList.list of EFI_SMM_DRIVER_ENTRY.
00082 //
00083 LIST_ENTRY  mScheduledQueue = INITIALIZE_LIST_HEAD_VARIABLE (mScheduledQueue);
00084 
00085 //
00086 // List of handles who's Fv's have been parsed and added to the mFwDriverList.
00087 //
00088 LIST_ENTRY  mFvHandleList = INITIALIZE_LIST_HEAD_VARIABLE (mFvHandleList);
00089 
00090 //
00091 // Flag for the SMM Dispacher.  TRUE if dispatcher is execuing.
00092 //
00093 BOOLEAN  gDispatcherRunning = FALSE;
00094 
00095 //
00096 // Flag for the SMM Dispacher.  TRUE if there is one or more SMM drivers ready to be dispatched
00097 //
00098 BOOLEAN  gRequestDispatch = FALSE;
00099 
00100 //
00101 // List of file types supported by dispatcher
00102 //
00103 EFI_FV_FILETYPE mSmmFileTypes[] = {
00104   EFI_FV_FILETYPE_SMM,
00105   EFI_FV_FILETYPE_COMBINED_SMM_DXE
00106   //
00107   // Note: DXE core will process the FV image file, so skip it in SMM core
00108   // EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
00109   //
00110 };
00111 
00112 typedef struct {
00113   MEDIA_FW_VOL_FILEPATH_DEVICE_PATH  File;
00114   EFI_DEVICE_PATH_PROTOCOL           End;
00115 } FV_FILEPATH_DEVICE_PATH;
00116 
00117 FV_FILEPATH_DEVICE_PATH  mFvDevicePath;
00118 
00119 //
00120 // DXE Architecture Protocols
00121 //
00122 EFI_SECURITY_ARCH_PROTOCOL  *mSecurity = NULL;
00123 
00124 //
00125 // The global variable is defined for Loading modules at fixed address feature to track the SMM code
00126 // memory range usage. It is a bit mapped array in which every bit indicates the correspoding 
00127 // memory page available or not. 
00128 //
00129 GLOBAL_REMOVE_IF_UNREFERENCED    UINT64                *mSmmCodeMemoryRangeUsageBitMap=NULL;
00130 
00142 EFI_STATUS
00143 CheckAndMarkFixLoadingMemoryUsageBitMap (
00144   IN  EFI_PHYSICAL_ADDRESS          ImageBase,
00145   IN  UINTN                         ImageSize
00146   )
00147 {
00148    UINT32                             SmmCodePageNumber;
00149    UINT64                             SmmCodeSize; 
00150    EFI_PHYSICAL_ADDRESS               SmmCodeBase;
00151    UINTN                              BaseOffsetPageNumber;
00152    UINTN                              TopOffsetPageNumber;
00153    UINTN                              Index;
00154    //
00155    // Build tool will calculate the smm code size and then patch the PcdLoadFixAddressSmmCodePageNumber
00156    //
00157    SmmCodePageNumber = PcdGet32(PcdLoadFixAddressSmmCodePageNumber);
00158    SmmCodeSize = EFI_PAGES_TO_SIZE (SmmCodePageNumber);
00159    SmmCodeBase = gLoadModuleAtFixAddressSmramBase;
00160    
00161    //
00162    // If the memory usage bit map is not initialized,  do it. Every bit in the array 
00163    // indicate the status of the corresponding memory page, available or not
00164    // 
00165    if (mSmmCodeMemoryRangeUsageBitMap == NULL) {
00166      mSmmCodeMemoryRangeUsageBitMap = AllocateZeroPool(((SmmCodePageNumber / 64) + 1)*sizeof(UINT64));
00167    }
00168    //
00169    // If the Dxe code memory range is not allocated or the bit map array allocation failed, return EFI_NOT_FOUND
00170    //
00171    if (mSmmCodeMemoryRangeUsageBitMap == NULL) {
00172      return EFI_NOT_FOUND;
00173    }
00174    //
00175    // see if the memory range for loading the image is in the SMM code range.
00176    //
00177    if (SmmCodeBase + SmmCodeSize <  ImageBase + ImageSize || SmmCodeBase >  ImageBase) {
00178      return EFI_NOT_FOUND;   
00179    }   
00180    //
00181    // Test if the memory is avalaible or not.
00182    // 
00183    BaseOffsetPageNumber = (UINTN)EFI_SIZE_TO_PAGES((UINT32)(ImageBase - SmmCodeBase));
00184    TopOffsetPageNumber  = (UINTN)EFI_SIZE_TO_PAGES((UINT32)(ImageBase + ImageSize - SmmCodeBase));
00185    for (Index = BaseOffsetPageNumber; Index < TopOffsetPageNumber; Index ++) {
00186      if ((mSmmCodeMemoryRangeUsageBitMap[Index / 64] & LShiftU64(1, (Index % 64))) != 0) {
00187        //
00188        // This page is already used.
00189        //
00190        return EFI_NOT_FOUND;  
00191      }
00192    }
00193    
00194    //
00195    // Being here means the memory range is available.  So mark the bits for the memory range
00196    // 
00197    for (Index = BaseOffsetPageNumber; Index < TopOffsetPageNumber; Index ++) {
00198      mSmmCodeMemoryRangeUsageBitMap[Index / 64] |= LShiftU64(1, (Index % 64));
00199    }
00200    return  EFI_SUCCESS;   
00201 }
00212 EFI_STATUS
00213 GetPeCoffImageFixLoadingAssignedAddress(
00214   IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext
00215   )
00216 {
00217          UINTN                              SectionHeaderOffset;
00218          EFI_STATUS                         Status;
00219          EFI_IMAGE_SECTION_HEADER           SectionHeader;
00220          EFI_IMAGE_OPTIONAL_HEADER_UNION    *ImgHdr;
00221          EFI_PHYSICAL_ADDRESS               FixLoaddingAddress;
00222          UINT16                             Index;
00223          UINTN                              Size; 
00224          UINT16                             NumberOfSections;
00225          UINT64                             ValueInSectionHeader;
00226          
00227          FixLoaddingAddress = 0;
00228          Status = EFI_NOT_FOUND;
00229         
00230          //
00231    // Get PeHeader pointer
00232    //
00233    ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((CHAR8* )ImageContext->Handle + ImageContext->PeCoffHeaderOffset);
00234          SectionHeaderOffset = (UINTN)(
00235                                  ImageContext->PeCoffHeaderOffset +
00236                                  sizeof (UINT32) +
00237                                  sizeof (EFI_IMAGE_FILE_HEADER) +
00238                                  ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader
00239                                  );
00240    NumberOfSections = ImgHdr->Pe32.FileHeader.NumberOfSections;
00241      
00242    //
00243    // Get base address from the first section header that doesn't point to code section.
00244    //
00245    for (Index = 0; Index < NumberOfSections; Index++) {
00246      //
00247      // Read section header from file
00248      //
00249      Size = sizeof (EFI_IMAGE_SECTION_HEADER);
00250      Status = ImageContext->ImageRead (
00251                               ImageContext->Handle,
00252                               SectionHeaderOffset,
00253                               &Size,
00254                               &SectionHeader
00255                               );
00256      if (EFI_ERROR (Status)) {
00257        return Status;
00258      }
00259      
00260      Status = EFI_NOT_FOUND;
00261      
00262      if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_CNT_CODE) == 0) {
00263        //
00264        // Build tool will save the address in PointerToRelocations & PointerToLineNumbers fields in the first section header 
00265        // that doesn't point to code section in image header.So there is an assumption that when the feature is enabled,
00266        // if a module with a loading address assigned by tools, the PointerToRelocations & PointerToLineNumbers fields
00267        // should not be Zero, or else, these 2 fileds should be set to Zero
00268        //
00269        ValueInSectionHeader = ReadUnaligned64((UINT64*)&SectionHeader.PointerToRelocations);
00270        if (ValueInSectionHeader != 0) {
00271          //
00272          // Found first section header that doesn't point to code section in which uild tool saves the
00273          // offset to SMRAM base as image base in PointerToRelocations & PointerToLineNumbers fields
00274          //      
00275          FixLoaddingAddress = (EFI_PHYSICAL_ADDRESS)(gLoadModuleAtFixAddressSmramBase + (INT64)ValueInSectionHeader);
00276          //
00277          // Check if the memory range is avaliable.
00278          //
00279          Status = CheckAndMarkFixLoadingMemoryUsageBitMap (FixLoaddingAddress, (UINTN)(ImageContext->ImageSize + ImageContext->SectionAlignment));
00280          if (!EFI_ERROR(Status)) {
00281            //
00282            // The assigned address is valid. Return the specified loadding address
00283            //
00284            ImageContext->ImageAddress = FixLoaddingAddress;
00285          }
00286        }
00287        break;     
00288      }
00289      SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER);     
00290    }
00291    DEBUG ((EFI_D_INFO|EFI_D_LOAD, "LOADING MODULE FIXED INFO: Loading module at fixed address %x, Status = %r\n", FixLoaddingAddress, Status));
00292    return Status;
00293 }
00302 EFI_STATUS
00303 EFIAPI
00304 SmmLoadImage (
00305   IN OUT EFI_SMM_DRIVER_ENTRY  *DriverEntry
00306   )
00307 {
00308   UINT32                         AuthenticationStatus;
00309   UINTN                          FilePathSize;
00310   VOID                           *Buffer;
00311   UINTN                          Size;
00312   UINTN                          PageCount;
00313   EFI_GUID                       *NameGuid;
00314   EFI_STATUS                     Status;
00315   EFI_STATUS                     SecurityStatus;
00316   EFI_HANDLE                     DeviceHandle;
00317   EFI_PHYSICAL_ADDRESS           DstBuffer;
00318   EFI_DEVICE_PATH_PROTOCOL       *FilePath;
00319   EFI_DEVICE_PATH_PROTOCOL       *OriginalFilePath;
00320   EFI_DEVICE_PATH_PROTOCOL       *HandleFilePath;
00321   EFI_FIRMWARE_VOLUME2_PROTOCOL  *Fv;
00322   PE_COFF_LOADER_IMAGE_CONTEXT   ImageContext;
00323    
00324   Buffer               = NULL;
00325   Size                 = 0;
00326   Fv                   = DriverEntry->Fv;
00327   NameGuid             = &DriverEntry->FileName;
00328   FilePath             = DriverEntry->FvFileDevicePath;
00329 
00330   OriginalFilePath     = FilePath;
00331   HandleFilePath       = FilePath;
00332   DeviceHandle         = NULL;
00333   SecurityStatus       = EFI_SUCCESS;
00334   Status               = EFI_SUCCESS;
00335   AuthenticationStatus = 0;
00336 
00337   //
00338   // Try to get the image device handle by checking the match protocol.
00339   //
00340   Status = gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid, &HandleFilePath, &DeviceHandle);
00341   if (EFI_ERROR(Status)) {
00342     return Status;
00343   }
00344 
00345   //
00346   // If the Security Architectural Protocol has not been located yet, then attempt to locate it
00347   //
00348   if (mSecurity == NULL) {
00349     gBS->LocateProtocol (&gEfiSecurityArchProtocolGuid, NULL, (VOID**)&mSecurity);
00350   }
00351 
00352   //
00353   // Verify the Authentication Status through the Security Architectural Protocol
00354   //
00355   if ((mSecurity != NULL) && (OriginalFilePath != NULL)) {
00356     SecurityStatus = mSecurity->FileAuthenticationState (
00357                                   mSecurity,
00358                                   AuthenticationStatus,
00359                                   OriginalFilePath
00360                                   );
00361     if (EFI_ERROR (SecurityStatus) && SecurityStatus != EFI_SECURITY_VIOLATION) {
00362       Status = SecurityStatus;
00363       return Status;
00364     }
00365   }
00366   
00367   //
00368   // Pull out just the file portion of the DevicePath for the LoadedImage FilePath
00369   //
00370   FilePath = OriginalFilePath;
00371   Status = gBS->HandleProtocol (DeviceHandle, &gEfiDevicePathProtocolGuid, (VOID **)&HandleFilePath);
00372   if (!EFI_ERROR (Status)) {
00373     FilePathSize = GetDevicePathSize (HandleFilePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL);
00374     FilePath = (EFI_DEVICE_PATH_PROTOCOL *) (((UINT8 *)FilePath) + FilePathSize );
00375   }
00376 
00377   //
00378   // Try reading PE32 section firstly
00379   //
00380   Status = Fv->ReadSection (
00381                  Fv,
00382                  NameGuid,
00383                  EFI_SECTION_PE32,
00384                  0,
00385                  &Buffer,
00386                  &Size,
00387                  &AuthenticationStatus
00388                  );
00389 
00390   if (EFI_ERROR (Status)) {
00391     //
00392     // Try reading TE section secondly
00393     //
00394     Buffer = NULL;
00395     Size   = 0;
00396     Status = Fv->ReadSection (
00397                   Fv,
00398                   NameGuid,
00399                   EFI_SECTION_TE,
00400                   0,
00401                   &Buffer,
00402                   &Size,
00403                   &AuthenticationStatus
00404                   );
00405   }
00406   
00407   if (EFI_ERROR (Status)) {
00408     if (Buffer != NULL) {
00409       Status = gBS->FreePool (Buffer);
00410     }
00411     return Status;
00412   }
00413 
00414   //
00415   // Initialize ImageContext
00416   //
00417   ImageContext.Handle = Buffer;
00418   ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;
00419 
00420   //
00421   // Get information about the image being loaded
00422   //
00423   Status = PeCoffLoaderGetImageInfo (&ImageContext);
00424   if (EFI_ERROR (Status)) {
00425     if (Buffer != NULL) {
00426       Status = gBS->FreePool (Buffer);
00427     }
00428     return Status;
00429   }
00430   //
00431   // if Loading module at Fixed Address feature is enabled, then  cut out a memory range started from TESG BASE
00432   // to hold the Smm driver code
00433   //
00434   if (PcdGet64(PcdLoadModuleAtFixAddressEnable) != 0) {
00435     //
00436     // Get the fixed loading address assigned by Build tool
00437     //
00438     Status = GetPeCoffImageFixLoadingAssignedAddress (&ImageContext);
00439     if (!EFI_ERROR (Status)) {
00440       //
00441       // Since the memory range to load Smm core alreay been cut out, so no need to allocate and free this range
00442       // following statements is to bypass SmmFreePages
00443       //
00444       PageCount = 0;
00445       DstBuffer = (UINTN)gLoadModuleAtFixAddressSmramBase;   
00446     } else {
00447        DEBUG ((EFI_D_INFO|EFI_D_LOAD, "LOADING MODULE FIXED ERROR: Failed to load module at fixed address. \n"));
00448        //
00449        // allocate the memory to load the SMM driver
00450        //
00451        PageCount = (UINTN)EFI_SIZE_TO_PAGES(ImageContext.ImageSize + ImageContext.SectionAlignment);
00452        DstBuffer = (UINTN)(-1);
00453      
00454        Status = SmmAllocatePages (
00455                    AllocateMaxAddress,
00456                    EfiRuntimeServicesCode,
00457                    PageCount,
00458                    &DstBuffer
00459                    );
00460        if (EFI_ERROR (Status)) {
00461          if (Buffer != NULL) {
00462            Status = gBS->FreePool (Buffer);
00463          } 
00464          return Status;
00465        }     
00466       ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)DstBuffer;
00467     }
00468   } else {
00469      PageCount = (UINTN)EFI_SIZE_TO_PAGES(ImageContext.ImageSize + ImageContext.SectionAlignment);
00470      DstBuffer = (UINTN)(-1);
00471      
00472      Status = SmmAllocatePages (
00473                   AllocateMaxAddress,
00474                   EfiRuntimeServicesCode,
00475                   PageCount,
00476                   &DstBuffer
00477                   );
00478      if (EFI_ERROR (Status)) {
00479        if (Buffer != NULL) {
00480          Status = gBS->FreePool (Buffer);
00481        }
00482        return Status;
00483      }
00484      
00485      ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)DstBuffer;
00486   }
00487   //
00488   // Align buffer on section boundry
00489   //
00490   ImageContext.ImageAddress += ImageContext.SectionAlignment - 1;
00491   ImageContext.ImageAddress &= ~(ImageContext.SectionAlignment - 1);
00492 
00493   //
00494   // Load the image to our new buffer
00495   //
00496   Status = PeCoffLoaderLoadImage (&ImageContext);
00497   if (EFI_ERROR (Status)) {
00498     if (Buffer != NULL) {
00499       Status = gBS->FreePool (Buffer);
00500     }
00501     SmmFreePages (DstBuffer, PageCount);
00502     return Status;
00503   }
00504 
00505   //
00506   // Relocate the image in our new buffer
00507   //
00508   Status = PeCoffLoaderRelocateImage (&ImageContext);
00509   if (EFI_ERROR (Status)) {
00510     if (Buffer != NULL) {
00511       Status = gBS->FreePool (Buffer);
00512     }
00513     SmmFreePages (DstBuffer, PageCount);
00514     return Status;
00515   }
00516 
00517   //
00518   // Flush the instruction cache so the image data are written before we execute it
00519   //
00520   InvalidateInstructionCacheRange ((VOID *)(UINTN) ImageContext.ImageAddress, (UINTN) ImageContext.ImageSize);
00521 
00522   //
00523   // Save Image EntryPoint in DriverEntry
00524   //
00525   DriverEntry->ImageEntryPoint  = ImageContext.EntryPoint;
00526   DriverEntry->ImageBuffer      = DstBuffer; 
00527   DriverEntry->NumberOfPage     = PageCount;
00528 
00529   //
00530   // Allocate a Loaded Image Protocol in EfiBootServicesData
00531   //
00532   Status = gBS->AllocatePool (EfiBootServicesData, sizeof (EFI_LOADED_IMAGE_PROTOCOL), (VOID **)&DriverEntry->LoadedImage);
00533   if (EFI_ERROR (Status)) {
00534     if (Buffer != NULL) {
00535       Status = gBS->FreePool (Buffer);
00536     }
00537     SmmFreePages (DstBuffer, PageCount);
00538     return Status;
00539   }
00540 
00541   //
00542   // Fill in the remaining fields of the Loaded Image Protocol instance.
00543   // Note: ImageBase is an SMRAM address that can not be accessed outside of SMRAM if SMRAM window is closed.
00544   //
00545   DriverEntry->LoadedImage->Revision      = EFI_LOADED_IMAGE_PROTOCOL_REVISION;
00546   DriverEntry->LoadedImage->ParentHandle  = gSmmCorePrivate->SmmIplImageHandle;
00547   DriverEntry->LoadedImage->SystemTable   = gST;
00548   DriverEntry->LoadedImage->DeviceHandle  = DeviceHandle;
00549 
00550   //
00551   // Make an EfiBootServicesData buffer copy of FilePath
00552   //
00553   Status = gBS->AllocatePool (EfiBootServicesData, GetDevicePathSize (FilePath), (VOID **)&DriverEntry->LoadedImage->FilePath);
00554   if (EFI_ERROR (Status)) {
00555     if (Buffer != NULL) {
00556       Status = gBS->FreePool (Buffer);
00557     }
00558     SmmFreePages (DstBuffer, PageCount);
00559     return Status;
00560   }
00561   CopyMem (DriverEntry->LoadedImage->FilePath, FilePath, GetDevicePathSize (FilePath));
00562 
00563   DriverEntry->LoadedImage->ImageBase     = (VOID *)(UINTN)DriverEntry->ImageBuffer;
00564   DriverEntry->LoadedImage->ImageSize     = ImageContext.ImageSize;
00565   DriverEntry->LoadedImage->ImageCodeType = EfiRuntimeServicesCode;
00566   DriverEntry->LoadedImage->ImageDataType = EfiRuntimeServicesData;
00567 
00568   //
00569   // Create a new image handle in the UEFI handle database for the SMM Driver
00570   //
00571   DriverEntry->ImageHandle = NULL;
00572   Status = gBS->InstallMultipleProtocolInterfaces (
00573                   &DriverEntry->ImageHandle,
00574                   &gEfiLoadedImageProtocolGuid, DriverEntry->LoadedImage,
00575                   NULL
00576                   );
00577 
00578   //
00579   // Print the load address and the PDB file name if it is available
00580   //
00581 
00582   DEBUG_CODE_BEGIN ();
00583 
00584     UINTN Index;
00585     UINTN StartIndex;
00586     CHAR8 EfiFileName[256];
00587 
00588 
00589     DEBUG ((DEBUG_INFO | DEBUG_LOAD,
00590            "Loading SMM driver at 0x%11p EntryPoint=0x%11p ",
00591            (VOID *)(UINTN) ImageContext.ImageAddress,
00592            FUNCTION_ENTRY_POINT (ImageContext.EntryPoint)));
00593 
00594 
00595     //
00596     // Print Module Name by Pdb file path.
00597     // Windows and Unix style file path are all trimmed correctly.
00598     //
00599     if (ImageContext.PdbPointer != NULL) {
00600       StartIndex = 0;
00601       for (Index = 0; ImageContext.PdbPointer[Index] != 0; Index++) {
00602         if ((ImageContext.PdbPointer[Index] == '\\') || (ImageContext.PdbPointer[Index] == '/')) {
00603           StartIndex = Index + 1;
00604         }
00605       }
00606       //
00607       // Copy the PDB file name to our temporary string, and replace .pdb with .efi
00608       // The PDB file name is limited in the range of 0~255.
00609       // If the length is bigger than 255, trim the redudant characters to avoid overflow in array boundary.
00610       //
00611       for (Index = 0; Index < sizeof (EfiFileName) - 4; Index++) {
00612         EfiFileName[Index] = ImageContext.PdbPointer[Index + StartIndex];
00613         if (EfiFileName[Index] == 0) {
00614           EfiFileName[Index] = '.';
00615         }
00616         if (EfiFileName[Index] == '.') {
00617           EfiFileName[Index + 1] = 'e';
00618           EfiFileName[Index + 2] = 'f';
00619           EfiFileName[Index + 3] = 'i';
00620           EfiFileName[Index + 4] = 0;
00621           break;
00622         }
00623       }
00624 
00625       if (Index == sizeof (EfiFileName) - 4) {
00626         EfiFileName[Index] = 0;
00627       }
00628       DEBUG ((DEBUG_INFO | DEBUG_LOAD, "%a", EfiFileName)); // &Image->ImageContext.PdbPointer[StartIndex]));
00629     }
00630     DEBUG ((DEBUG_INFO | DEBUG_LOAD, "\n"));
00631 
00632   DEBUG_CODE_END ();
00633 
00634   //
00635   // Free buffer allocated by Fv->ReadSection.
00636   //
00637   // The UEFI Boot Services FreePool() function must be used because Fv->ReadSection 
00638   // used the UEFI Boot Services AllocatePool() function
00639   //
00640   Status = gBS->FreePool(Buffer);
00641   return Status;  
00642 }
00643 
00654 EFI_STATUS
00655 SmmPreProcessDepex (
00656   IN EFI_SMM_DRIVER_ENTRY  *DriverEntry
00657   )
00658 {
00659   UINT8  *Iterator;
00660 
00661   Iterator = DriverEntry->Depex;
00662   DriverEntry->Dependent = TRUE;
00663 
00664   if (*Iterator == EFI_DEP_BEFORE) {
00665     DriverEntry->Before = TRUE;
00666   } else if (*Iterator == EFI_DEP_AFTER) {
00667     DriverEntry->After = TRUE;
00668   }
00669 
00670   if (DriverEntry->Before || DriverEntry->After) {
00671     CopyMem (&DriverEntry->BeforeAfterGuid, Iterator + 1, sizeof (EFI_GUID));
00672   }
00673 
00674   return EFI_SUCCESS;
00675 }
00676 
00689 EFI_STATUS
00690 SmmGetDepexSectionAndPreProccess (
00691   IN EFI_SMM_DRIVER_ENTRY  *DriverEntry
00692   )
00693 {
00694   EFI_STATUS                     Status;
00695   EFI_SECTION_TYPE               SectionType;
00696   UINT32                         AuthenticationStatus;
00697   EFI_FIRMWARE_VOLUME2_PROTOCOL  *Fv;
00698 
00699   Fv = DriverEntry->Fv;
00700 
00701   //
00702   // Grab Depex info, it will never be free'ed.
00703   // (Note: DriverEntry->Depex is in DXE memory)
00704   //
00705   SectionType         = EFI_SECTION_SMM_DEPEX;
00706   Status = Fv->ReadSection (
00707                 DriverEntry->Fv,
00708                 &DriverEntry->FileName,
00709                 SectionType,
00710                 0,
00711                 &DriverEntry->Depex,
00712                 (UINTN *)&DriverEntry->DepexSize,
00713                 &AuthenticationStatus
00714                 );
00715   if (EFI_ERROR (Status)) {
00716     if (Status == EFI_PROTOCOL_ERROR) {
00717       //
00718       // The section extraction protocol failed so set protocol error flag
00719       //
00720       DriverEntry->DepexProtocolError = TRUE;
00721     } else {
00722       //
00723       // If no Depex assume depend on all architectural protocols
00724       //
00725       DriverEntry->Depex = NULL;
00726       DriverEntry->Dependent = TRUE;
00727       DriverEntry->DepexProtocolError = FALSE;
00728     }
00729   } else {
00730     //
00731     // Set Before and After state information based on Depex
00732     // Driver will be put in Dependent state
00733     //
00734     SmmPreProcessDepex (DriverEntry);
00735     DriverEntry->DepexProtocolError = FALSE;
00736   }
00737 
00738   return Status;
00739 }
00740 
00757 EFI_STATUS
00758 SmmDispatcher (
00759   VOID
00760   )
00761 {
00762   EFI_STATUS            Status;
00763   LIST_ENTRY            *Link;
00764   EFI_SMM_DRIVER_ENTRY  *DriverEntry;
00765   BOOLEAN               ReadyToRun;
00766   BOOLEAN               PreviousSmmEntryPointRegistered;
00767 
00768   if (!gRequestDispatch) {
00769     return EFI_NOT_FOUND;
00770   }
00771 
00772   if (gDispatcherRunning) {
00773     //
00774     // If the dispatcher is running don't let it be restarted.
00775     //
00776     return EFI_ALREADY_STARTED;
00777   }
00778 
00779   gDispatcherRunning = TRUE;
00780 
00781   do {
00782     //
00783     // Drain the Scheduled Queue
00784     //
00785     while (!IsListEmpty (&mScheduledQueue)) {
00786       DriverEntry = CR (
00787                       mScheduledQueue.ForwardLink,
00788                       EFI_SMM_DRIVER_ENTRY,
00789                       ScheduledLink,
00790                       EFI_SMM_DRIVER_ENTRY_SIGNATURE
00791                       );
00792 
00793       //
00794       // Load the SMM Driver image into memory. If the Driver was transitioned from
00795       // Untrused to Scheduled it would have already been loaded so we may need to
00796       // skip the LoadImage
00797       //
00798       if (DriverEntry->ImageHandle == NULL) {
00799         Status = SmmLoadImage (DriverEntry);
00800 
00801         //
00802         // Update the driver state to reflect that it's been loaded
00803         //
00804         if (EFI_ERROR (Status)) {
00805           //
00806           // The SMM Driver could not be loaded, and do not attempt to load or start it again.
00807           // Take driver from Scheduled to Initialized.
00808           //
00809           DriverEntry->Initialized  = TRUE;
00810           DriverEntry->Scheduled = FALSE;
00811           RemoveEntryList (&DriverEntry->ScheduledLink);
00812 
00813           //
00814           // If it's an error don't try the StartImage
00815           //
00816           continue;
00817         }
00818       }
00819 
00820       DriverEntry->Scheduled    = FALSE;
00821       DriverEntry->Initialized  = TRUE;
00822       RemoveEntryList (&DriverEntry->ScheduledLink);
00823 
00824       REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
00825         EFI_PROGRESS_CODE,
00826         EFI_SOFTWARE_SMM_DRIVER | EFI_SW_PC_INIT_BEGIN,
00827         &DriverEntry->ImageHandle,
00828         sizeof (DriverEntry->ImageHandle)
00829         );
00830 
00831       //
00832       // Cache state of SmmEntryPointRegistered before calling entry point
00833       //
00834       PreviousSmmEntryPointRegistered = gSmmCorePrivate->SmmEntryPointRegistered;
00835 
00836       //
00837       // For each SMM driver, pass NULL as ImageHandle
00838       //
00839       Status = ((EFI_IMAGE_ENTRY_POINT)(UINTN)DriverEntry->ImageEntryPoint)(DriverEntry->ImageHandle, gST);
00840       if (EFI_ERROR(Status)){
00841         SmmFreePages(DriverEntry->ImageBuffer, DriverEntry->NumberOfPage);
00842       }
00843 
00844       REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
00845         EFI_PROGRESS_CODE,
00846         EFI_SOFTWARE_SMM_DRIVER | EFI_SW_PC_INIT_END,
00847         &DriverEntry->ImageHandle,
00848         sizeof (DriverEntry->ImageHandle)
00849         );
00850 
00851       if (!PreviousSmmEntryPointRegistered && gSmmCorePrivate->SmmEntryPointRegistered) {
00852         //
00853         // Return immediately if the SMM Entry Point was registered by the SMM 
00854         // Driver that was just dispatched.  The SMM IPL will reinvoke the SMM
00855         // Core Dispatcher.  This is required so SMM Mode may be enabled as soon 
00856         // as all the dependent SMM Drivers for SMM Mode have been dispatched.  
00857         // Once the SMM Entry Point has been registered, then SMM Mode will be 
00858         // used.
00859         //
00860         gRequestDispatch = TRUE;
00861         gDispatcherRunning = FALSE;
00862         return EFI_NOT_READY;
00863       }
00864     }
00865 
00866     //
00867     // Search DriverList for items to place on Scheduled Queue
00868     //
00869     ReadyToRun = FALSE;
00870     for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {
00871       DriverEntry = CR (Link, EFI_SMM_DRIVER_ENTRY, Link, EFI_SMM_DRIVER_ENTRY_SIGNATURE);
00872 
00873       if (DriverEntry->DepexProtocolError){
00874         //
00875         // If Section Extraction Protocol did not let the Depex be read before retry the read
00876         //
00877         Status = SmmGetDepexSectionAndPreProccess (DriverEntry);
00878       }
00879 
00880       if (DriverEntry->Dependent) {
00881         if (SmmIsSchedulable (DriverEntry)) {
00882           SmmInsertOnScheduledQueueWhileProcessingBeforeAndAfter (DriverEntry);
00883           ReadyToRun = TRUE;
00884         }
00885       }
00886     }
00887   } while (ReadyToRun);
00888 
00889   //
00890   // If there is no more SMM driver to dispatch, stop the dispatch request
00891   //
00892   gRequestDispatch = FALSE;
00893   for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {
00894     DriverEntry = CR (Link, EFI_SMM_DRIVER_ENTRY, Link, EFI_SMM_DRIVER_ENTRY_SIGNATURE);
00895 
00896     if (!DriverEntry->Initialized){
00897       //
00898       // We have SMM driver pending to dispatch
00899       //
00900       gRequestDispatch = TRUE;
00901       break;
00902     }
00903   }
00904 
00905   gDispatcherRunning = FALSE;
00906 
00907   return EFI_SUCCESS;
00908 }
00909 
00921 VOID
00922 SmmInsertOnScheduledQueueWhileProcessingBeforeAndAfter (
00923   IN  EFI_SMM_DRIVER_ENTRY   *InsertedDriverEntry
00924   )
00925 {
00926   LIST_ENTRY            *Link;
00927   EFI_SMM_DRIVER_ENTRY *DriverEntry;
00928 
00929   //
00930   // Process Before Dependency
00931   //
00932   for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {
00933     DriverEntry = CR(Link, EFI_SMM_DRIVER_ENTRY, Link, EFI_SMM_DRIVER_ENTRY_SIGNATURE);
00934     if (DriverEntry->Before && DriverEntry->Dependent && DriverEntry != InsertedDriverEntry) {
00935       DEBUG ((DEBUG_DISPATCH, "Evaluate SMM DEPEX for FFS(%g)\n", &DriverEntry->FileName));
00936       DEBUG ((DEBUG_DISPATCH, "  BEFORE FFS(%g) = ", &DriverEntry->BeforeAfterGuid));
00937       if (CompareGuid (&InsertedDriverEntry->FileName, &DriverEntry->BeforeAfterGuid)) {
00938         //
00939         // Recursively process BEFORE
00940         //
00941         DEBUG ((DEBUG_DISPATCH, "TRUE\n  END\n  RESULT = TRUE\n"));
00942         SmmInsertOnScheduledQueueWhileProcessingBeforeAndAfter (DriverEntry);
00943       } else {
00944         DEBUG ((DEBUG_DISPATCH, "FALSE\n  END\n  RESULT = FALSE\n"));
00945       }
00946     }
00947   }
00948 
00949   //
00950   // Convert driver from Dependent to Scheduled state
00951   //
00952 
00953   InsertedDriverEntry->Dependent = FALSE;
00954   InsertedDriverEntry->Scheduled = TRUE;
00955   InsertTailList (&mScheduledQueue, &InsertedDriverEntry->ScheduledLink);
00956 
00957 
00958   //
00959   // Process After Dependency
00960   //
00961   for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {
00962     DriverEntry = CR(Link, EFI_SMM_DRIVER_ENTRY, Link, EFI_SMM_DRIVER_ENTRY_SIGNATURE);
00963     if (DriverEntry->After && DriverEntry->Dependent && DriverEntry != InsertedDriverEntry) {
00964       DEBUG ((DEBUG_DISPATCH, "Evaluate SMM DEPEX for FFS(%g)\n", &DriverEntry->FileName));
00965       DEBUG ((DEBUG_DISPATCH, "  AFTER FFS(%g) = ", &DriverEntry->BeforeAfterGuid));
00966       if (CompareGuid (&InsertedDriverEntry->FileName, &DriverEntry->BeforeAfterGuid)) {
00967         //
00968         // Recursively process AFTER
00969         //
00970         DEBUG ((DEBUG_DISPATCH, "TRUE\n  END\n  RESULT = TRUE\n"));
00971         SmmInsertOnScheduledQueueWhileProcessingBeforeAndAfter (DriverEntry);
00972       } else {
00973         DEBUG ((DEBUG_DISPATCH, "FALSE\n  END\n  RESULT = FALSE\n"));
00974       }
00975     }
00976   }
00977 }
00978 
00989 BOOLEAN
00990 FvHasBeenProcessed (
00991   IN EFI_HANDLE  FvHandle
00992   )
00993 {
00994   LIST_ENTRY    *Link;
00995   KNOWN_HANDLE  *KnownHandle;
00996 
00997   for (Link = mFvHandleList.ForwardLink; Link != &mFvHandleList; Link = Link->ForwardLink) {
00998     KnownHandle = CR(Link, KNOWN_HANDLE, Link, KNOWN_HANDLE_SIGNATURE);
00999     if (KnownHandle->Handle == FvHandle) {
01000       return TRUE;
01001     }
01002   }
01003   return FALSE;
01004 }
01005 
01014 VOID
01015 FvIsBeingProcesssed (
01016   IN EFI_HANDLE  FvHandle
01017   )
01018 {
01019   KNOWN_HANDLE  *KnownHandle;
01020 
01021   KnownHandle = AllocatePool (sizeof (KNOWN_HANDLE));
01022   ASSERT (KnownHandle != NULL);
01023 
01024   KnownHandle->Signature = KNOWN_HANDLE_SIGNATURE;
01025   KnownHandle->Handle = FvHandle;
01026   InsertTailList (&mFvHandleList, &KnownHandle->Link);
01027 }
01028 
01042 EFI_DEVICE_PATH_PROTOCOL *
01043 SmmFvToDevicePath (
01044   IN  EFI_FIRMWARE_VOLUME2_PROTOCOL   *Fv,
01045   IN  EFI_HANDLE                      FvHandle,
01046   IN  EFI_GUID                        *DriverName
01047   )
01048 {
01049   EFI_STATUS                          Status;
01050   EFI_DEVICE_PATH_PROTOCOL            *FvDevicePath;
01051   EFI_DEVICE_PATH_PROTOCOL            *FileNameDevicePath;
01052 
01053   //
01054   // Remember the device path of the FV
01055   //
01056   Status = gBS->HandleProtocol (FvHandle, &gEfiDevicePathProtocolGuid, (VOID **)&FvDevicePath);
01057   if (EFI_ERROR (Status)) {
01058     FileNameDevicePath = NULL;
01059   } else {
01060     //
01061     // Build a device path to the file in the FV to pass into gBS->LoadImage
01062     //
01063     EfiInitializeFwVolDevicepathNode (&mFvDevicePath.File, DriverName);
01064     SetDevicePathEndNode (&mFvDevicePath.End);
01065 
01066     //
01067     // Note: FileNameDevicePath is in DXE memory
01068     //
01069     FileNameDevicePath = AppendDevicePath (
01070                             FvDevicePath,
01071                             (EFI_DEVICE_PATH_PROTOCOL *)&mFvDevicePath
01072                             );
01073   }
01074   return FileNameDevicePath;
01075 }
01076 
01097 EFI_STATUS
01098 SmmAddToDriverList (
01099   IN EFI_FIRMWARE_VOLUME2_PROTOCOL  *Fv,
01100   IN EFI_HANDLE                     FvHandle,
01101   IN EFI_GUID                       *DriverName
01102   )
01103 {
01104   EFI_SMM_DRIVER_ENTRY  *DriverEntry;
01105 
01106   //
01107   // Create the Driver Entry for the list. ZeroPool initializes lots of variables to
01108   // NULL or FALSE.
01109   //
01110   DriverEntry = AllocateZeroPool (sizeof (EFI_SMM_DRIVER_ENTRY));
01111   ASSERT (DriverEntry != NULL);
01112 
01113   DriverEntry->Signature        = EFI_SMM_DRIVER_ENTRY_SIGNATURE;
01114   CopyGuid (&DriverEntry->FileName, DriverName);
01115   DriverEntry->FvHandle         = FvHandle;
01116   DriverEntry->Fv               = Fv;
01117   DriverEntry->FvFileDevicePath = SmmFvToDevicePath (Fv, FvHandle, DriverName);
01118 
01119   SmmGetDepexSectionAndPreProccess (DriverEntry);
01120 
01121   InsertTailList (&mDiscoveredList, &DriverEntry->Link);
01122   gRequestDispatch = TRUE;
01123 
01124   return EFI_SUCCESS;
01125 }
01126 
01152 EFI_STATUS
01153 EFIAPI
01154 SmmDriverDispatchHandler (
01155   IN     EFI_HANDLE  DispatchHandle,
01156   IN     CONST VOID  *Context,        OPTIONAL
01157   IN OUT VOID        *CommBuffer,     OPTIONAL
01158   IN OUT UINTN       *CommBufferSize  OPTIONAL
01159   )
01160 {
01161   EFI_STATUS                    Status;
01162   UINTN                         HandleCount;
01163   EFI_HANDLE                    *HandleBuffer;
01164   EFI_STATUS                    GetNextFileStatus;
01165   EFI_STATUS                    SecurityStatus;
01166   EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;
01167   EFI_DEVICE_PATH_PROTOCOL      *FvDevicePath;
01168   EFI_HANDLE                    FvHandle;
01169   EFI_GUID                      NameGuid;
01170   UINTN                         Key;
01171   EFI_FV_FILETYPE               Type;
01172   EFI_FV_FILE_ATTRIBUTES        Attributes;
01173   UINTN                         Size;
01174   EFI_SMM_DRIVER_ENTRY          *DriverEntry;
01175   EFI_GUID                      *AprioriFile;
01176   UINTN                         AprioriEntryCount;
01177   UINTN                         Index;
01178   LIST_ENTRY                    *Link;
01179   UINT32                        AuthenticationStatus;
01180   UINTN                         SizeOfBuffer;
01181 
01182   HandleBuffer = NULL;
01183   Status = gBS->LocateHandleBuffer (
01184                   ByProtocol,
01185                   &gEfiFirmwareVolume2ProtocolGuid,
01186                   NULL,
01187                   &HandleCount,
01188                   &HandleBuffer
01189                   );
01190   if (EFI_ERROR (Status)) {
01191     return EFI_NOT_FOUND;
01192   }
01193 
01194   for (Index = 0; Index < HandleCount; Index++) {
01195     FvHandle = HandleBuffer[Index];
01196 
01197     if (FvHasBeenProcessed (FvHandle)) {
01198       //
01199       // This Fv has already been processed so lets skip it!
01200       //
01201       continue;
01202     }
01203 
01204     //
01205     // Since we are about to process this Fv mark it as processed.
01206     //
01207     FvIsBeingProcesssed (FvHandle);
01208 
01209     Status = gBS->HandleProtocol (FvHandle, &gEfiFirmwareVolume2ProtocolGuid, (VOID **)&Fv);
01210     if (EFI_ERROR (Status)) {
01211       //
01212       // FvHandle must have a Firmware Volume2 Protocol thus we should never get here.
01213       //
01214       ASSERT (FALSE);
01215       continue;
01216     }
01217 
01218     Status = gBS->HandleProtocol (FvHandle, &gEfiDevicePathProtocolGuid, (VOID **)&FvDevicePath);
01219     if (EFI_ERROR (Status)) {
01220       //
01221       // The Firmware volume doesn't have device path, can't be dispatched.
01222       //
01223       continue;
01224     }
01225 
01226     //
01227     // If the Security Architectural Protocol has not been located yet, then attempt to locate it
01228     //
01229     if (mSecurity == NULL) {
01230       gBS->LocateProtocol (&gEfiSecurityArchProtocolGuid, NULL, (VOID**)&mSecurity);
01231     }
01232 
01233     //
01234     // Evaluate the authentication status of the Firmware Volume through
01235     // Security Architectural Protocol
01236     //
01237     if (mSecurity != NULL) {
01238       SecurityStatus = mSecurity->FileAuthenticationState (
01239                                     mSecurity,
01240                                     0,
01241                                     FvDevicePath
01242                                     );
01243       if (SecurityStatus != EFI_SUCCESS) {
01244         //
01245         // Security check failed. The firmware volume should not be used for any purpose.
01246         //
01247         continue;
01248       }
01249     }
01250 
01251     //
01252     // Discover Drivers in FV and add them to the Discovered Driver List.
01253     // Process EFI_FV_FILETYPE_SMM type and then EFI_FV_FILETYPE_COMBINED_SMM_DXE
01254     //
01255     for (Index = 0; Index < sizeof (mSmmFileTypes)/sizeof (EFI_FV_FILETYPE); Index++) {
01256       //
01257       // Initialize the search key
01258       //
01259       Key = 0;
01260       do {
01261         Type = mSmmFileTypes[Index];
01262         GetNextFileStatus = Fv->GetNextFile (
01263                                   Fv,
01264                                   &Key,
01265                                   &Type,
01266                                   &NameGuid,
01267                                   &Attributes,
01268                                   &Size
01269                                   );
01270         if (!EFI_ERROR (GetNextFileStatus)) {
01271           SmmAddToDriverList (Fv, FvHandle, &NameGuid);
01272         }
01273       } while (!EFI_ERROR (GetNextFileStatus));
01274     }
01275 
01276     //
01277     // Read the array of GUIDs from the Apriori file if it is present in the firmware volume
01278     // (Note: AprioriFile is in DXE memory)
01279     //
01280     AprioriFile = NULL;
01281     Status = Fv->ReadSection (
01282                   Fv,
01283                   &gAprioriGuid,
01284                   EFI_SECTION_RAW,
01285                   0,
01286                   (VOID **)&AprioriFile,
01287                   &SizeOfBuffer,
01288                   &AuthenticationStatus
01289                   );
01290     if (!EFI_ERROR (Status)) {
01291       AprioriEntryCount = SizeOfBuffer / sizeof (EFI_GUID);
01292     } else {
01293       AprioriEntryCount = 0;
01294     }
01295 
01296     //
01297     // Put drivers on Apriori List on the Scheduled queue. The Discovered List includes
01298     // drivers not in the current FV and these must be skipped since the a priori list
01299     // is only valid for the FV that it resided in.
01300     //
01301 
01302     for (Index = 0; Index < AprioriEntryCount; Index++) {
01303       for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {
01304         DriverEntry = CR(Link, EFI_SMM_DRIVER_ENTRY, Link, EFI_SMM_DRIVER_ENTRY_SIGNATURE);
01305         if (CompareGuid (&DriverEntry->FileName, &AprioriFile[Index]) &&
01306             (FvHandle == DriverEntry->FvHandle)) {
01307           DriverEntry->Dependent = FALSE;
01308           DriverEntry->Scheduled = TRUE;
01309           InsertTailList (&mScheduledQueue, &DriverEntry->ScheduledLink);
01310           DEBUG ((DEBUG_DISPATCH, "Evaluate SMM DEPEX for FFS(%g)\n", &DriverEntry->FileName));
01311           DEBUG ((DEBUG_DISPATCH, "  RESULT = TRUE (Apriori)\n"));
01312           break;
01313         }
01314       }
01315     }
01316 
01317     //
01318     // Free data allocated by Fv->ReadSection ()
01319     //
01320     // The UEFI Boot Services FreePool() function must be used because Fv->ReadSection 
01321     // used the UEFI Boot Services AllocatePool() function
01322     //
01323     gBS->FreePool (AprioriFile);
01324   }
01325 
01326   //
01327   // Execute the SMM Dispatcher on any newly discovered FVs and previously 
01328   // discovered SMM drivers that have been discovered but not dispatched.
01329   //
01330   Status = SmmDispatcher ();
01331 
01332   //
01333   // Check to see if CommBuffer and CommBufferSize are valid
01334   //
01335   if (CommBuffer != NULL && CommBufferSize != NULL) {
01336     if (*CommBufferSize > 0) {
01337       if (Status == EFI_NOT_READY) {
01338         //
01339         // If a the SMM Core Entry Point was just registered, then set flag to 
01340         // request the SMM Dispatcher to be restarted.
01341         //
01342         *(UINT8 *)CommBuffer = COMM_BUFFER_SMM_DISPATCH_RESTART;
01343       } else if (!EFI_ERROR (Status)) {
01344         //
01345         // Set the flag to show that the SMM Dispatcher executed without errors
01346         //
01347         *(UINT8 *)CommBuffer = COMM_BUFFER_SMM_DISPATCH_SUCCESS;
01348       } else {
01349         //
01350         // Set the flag to show that the SMM Dispatcher encountered an error
01351         //
01352         *(UINT8 *)CommBuffer = COMM_BUFFER_SMM_DISPATCH_ERROR;
01353       }
01354     }
01355   }
01356 
01357   return EFI_SUCCESS;
01358 }
01359 
01365 VOID
01366 SmmDisplayDiscoveredNotDispatched (
01367   VOID
01368   )
01369 {
01370   LIST_ENTRY                   *Link;
01371   EFI_SMM_DRIVER_ENTRY         *DriverEntry;
01372 
01373   for (Link = mDiscoveredList.ForwardLink;Link !=&mDiscoveredList; Link = Link->ForwardLink) {
01374     DriverEntry = CR(Link, EFI_SMM_DRIVER_ENTRY, Link, EFI_SMM_DRIVER_ENTRY_SIGNATURE);
01375     if (DriverEntry->Dependent) {
01376       DEBUG ((DEBUG_LOAD, "SMM Driver %g was discovered but not loaded!!\n", &DriverEntry->FileName));
01377     }
01378   }
01379 }
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Defines