EFI_STATUS UtilGetSystemMemoryResources ( IN LIST_ENTRY *ResourceList ) { EFI_HOB_RESOURCE_DESCRIPTOR *ResHob; InitializeListHead (ResourceList); // Find the first System Memory Resource Descriptor ResHob = (EFI_HOB_RESOURCE_DESCRIPTOR *)GetFirstHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR); while ((ResHob != NULL) && (ResHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY)) { ResHob = (EFI_HOB_RESOURCE_DESCRIPTOR *)GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, (VOID *)((UINTN)ResHob + ResHob->Header.HobLength)); } // Did not find any if (ResHob == NULL) { return EFI_NOT_FOUND; } else { InsertSystemMemoryResources (ResourceList, ResHob); } ResHob = (EFI_HOB_RESOURCE_DESCRIPTOR *)GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, (VOID *)((UINTN)ResHob + ResHob->Header.HobLength)); while (ResHob != NULL) { if (ResHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) { InsertSystemMemoryResources (ResourceList, ResHob); } ResHob = (EFI_HOB_RESOURCE_DESCRIPTOR *)GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, (VOID *)((UINTN)ResHob + ResHob->Header.HobLength)); } return EFI_SUCCESS; }
/** This function initializes the mCapsulePtr, mCapsuleStatusArray and mCapsuleTotalNumber. **/ VOID InitCapsulePtr ( VOID ) { EFI_PEI_HOB_POINTERS HobPointer; UINTN Index; // // Find all capsule images from hob // HobPointer.Raw = GetHobList (); while ((HobPointer.Raw = GetNextHob (EFI_HOB_TYPE_UEFI_CAPSULE, HobPointer.Raw)) != NULL) { if (!IsValidCapsuleHeader((VOID *)(UINTN)HobPointer.Capsule->BaseAddress, HobPointer.Capsule->Length)) { HobPointer.Header->HobType = EFI_HOB_TYPE_UNUSED; // Mark this hob as invalid } else { mCapsuleTotalNumber++; } HobPointer.Raw = GET_NEXT_HOB (HobPointer); } DEBUG ((DEBUG_INFO, "mCapsuleTotalNumber - 0x%x\n", mCapsuleTotalNumber)); if (mCapsuleTotalNumber == 0) { return ; } // // Init temp Capsule Data table. // mCapsulePtr = (VOID **) AllocateZeroPool (sizeof (VOID *) * mCapsuleTotalNumber); if (mCapsulePtr == NULL) { DEBUG ((DEBUG_ERROR, "Allocate mCapsulePtr fail!\n")); mCapsuleTotalNumber = 0; return ; } mCapsuleStatusArray = (EFI_STATUS *) AllocateZeroPool (sizeof (EFI_STATUS) * mCapsuleTotalNumber); if (mCapsuleStatusArray == NULL) { DEBUG ((DEBUG_ERROR, "Allocate mCapsuleStatusArray fail!\n")); FreePool (mCapsulePtr); mCapsulePtr = NULL; mCapsuleTotalNumber = 0; return ; } SetMemN (mCapsuleStatusArray, sizeof (EFI_STATUS) * mCapsuleTotalNumber, EFI_NOT_READY); // // Find all capsule images from hob // HobPointer.Raw = GetHobList (); Index = 0; while ((HobPointer.Raw = GetNextHob (EFI_HOB_TYPE_UEFI_CAPSULE, HobPointer.Raw)) != NULL) { mCapsulePtr [Index++] = (VOID *) (UINTN) HobPointer.Capsule->BaseAddress; HobPointer.Raw = GET_NEXT_HOB (HobPointer); } }
/** Updates the Stack HOB passed to DXE phase. This function traverses the whole HOB list and update the stack HOB to reflect the real stack that is used by DXE core. @param BaseAddress The lower address of stack used by DxeCore. @param Length The length of stack used by DxeCore. **/ VOID UpdateStackHob ( IN EFI_PHYSICAL_ADDRESS BaseAddress, IN UINT64 Length ) { EFI_PEI_HOB_POINTERS Hob; Hob.Raw = GetHobList (); while ((Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw)) != NULL) { if (CompareGuid (&gEfiHobMemoryAllocStackGuid, &(Hob.MemoryAllocationStack->AllocDescriptor.Name))) { // // Build a new memory allocation HOB with old stack info with EfiBootServicesData type. Need to // avoid this region be reclaimed by DXE core as the IDT built in SEC might be on stack, and some // PEIMs may also keep key information on stack // BuildMemoryAllocationHob ( Hob.MemoryAllocationStack->AllocDescriptor.MemoryBaseAddress, Hob.MemoryAllocationStack->AllocDescriptor.MemoryLength, EfiBootServicesData ); // // Update the BSP Stack Hob to reflect the new stack info. // Hob.MemoryAllocationStack->AllocDescriptor.MemoryBaseAddress = BaseAddress; Hob.MemoryAllocationStack->AllocDescriptor.MemoryLength = Length; break; } Hob.Raw = GET_NEXT_HOB (Hob); } }
/** Update the Stack Hob if the stack has been moved @param BaseAddress The 64 bit physical address of the Stack. @param Length The length of the stack in bytes. **/ VOID UpdateStackHob ( IN EFI_PHYSICAL_ADDRESS BaseAddress, IN UINT64 Length ) { EFI_PEI_HOB_POINTERS Hob; Hob.Raw = GetHobList (); while ((Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw)) != NULL) { if (CompareGuid (&gEfiHobMemoryAllocStackGuid, &(Hob.MemoryAllocationStack->AllocDescriptor.Name))) { // // Build a new memory allocation HOB with old stack info with EfiConventionalMemory type // to be reclaimed by DXE core. // BuildMemoryAllocationHob ( Hob.MemoryAllocationStack->AllocDescriptor.MemoryBaseAddress, Hob.MemoryAllocationStack->AllocDescriptor.MemoryLength, EfiConventionalMemory ); // // Update the BSP Stack Hob to reflect the new stack info. // Hob.MemoryAllocationStack->AllocDescriptor.MemoryBaseAddress = BaseAddress; Hob.MemoryAllocationStack->AllocDescriptor.MemoryLength = Length; break; } Hob.Raw = GET_NEXT_HOB (Hob); } }
EFIAPI GetFirstHob ( IN UINT16 Type ) { VOID *HobList; HobList = GetHobList (); return GetNextHob (Type, HobList); }
/** Hook point for AcpiVariableThunkPlatform for S3Ready. @param AcpiS3Context ACPI s3 context **/ VOID S3ReadyThunkPlatform ( IN ACPI_S3_CONTEXT *AcpiS3Context ) { EFI_PHYSICAL_ADDRESS AcpiMemoryBase; UINT32 AcpiMemorySize; EFI_PEI_HOB_POINTERS Hob; UINT64 MemoryLength; DEBUG ((EFI_D_INFO, "S3ReadyThunkPlatform\n")); if (mAcpiVariableSetCompatibility == NULL) { return; } // // Allocate ACPI reserved memory under 4G // AcpiMemoryBase = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateMemoryBelow4G (EfiReservedMemoryType, PcdGet32 (PcdS3AcpiReservedMemorySize)); ASSERT (AcpiMemoryBase != 0); AcpiMemorySize = PcdGet32 (PcdS3AcpiReservedMemorySize); // // Calculate the system memory length by memory hobs // MemoryLength = 0x100000; Hob.Raw = GetFirstHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR); ASSERT (Hob.Raw != NULL); while ((Hob.Raw != NULL) && (!END_OF_HOB_LIST (Hob))) { if (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) { // // Skip the memory region below 1MB // if (Hob.ResourceDescriptor->PhysicalStart >= 0x100000) { MemoryLength += Hob.ResourceDescriptor->ResourceLength; } } Hob.Raw = GET_NEXT_HOB (Hob); Hob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, Hob.Raw); } mAcpiVariableSetCompatibility->AcpiReservedMemoryBase = AcpiMemoryBase; mAcpiVariableSetCompatibility->AcpiReservedMemorySize = AcpiMemorySize; mAcpiVariableSetCompatibility->SystemMemoryLength = MemoryLength; DEBUG((EFI_D_INFO, "AcpiVariableThunkPlatform: AcpiMemoryBase is 0x%8x\n", mAcpiVariableSetCompatibility->AcpiReservedMemoryBase)); DEBUG((EFI_D_INFO, "AcpiVariableThunkPlatform: AcpiMemorySize is 0x%8x\n", mAcpiVariableSetCompatibility->AcpiReservedMemorySize)); DEBUG((EFI_D_INFO, "AcpiVariableThunkPlatform: SystemMemoryLength is 0x%8x\n", mAcpiVariableSetCompatibility->SystemMemoryLength)); return ; }
EFIAPI GetNextGuidHob ( IN CONST EFI_GUID *Guid, IN CONST VOID *HobStart ){ EFI_PEI_HOB_POINTERS GuidHob; GuidHob.Raw = (UINT8 *) HobStart; while ((GuidHob.Raw = GetNextHob (EFI_HOB_TYPE_GUID_EXTENSION, GuidHob.Raw)) != NULL) { if (CompareGuid (Guid, &GuidHob.Guid->Name)) { break; } GuidHob.Raw = GET_NEXT_HOB (GuidHob); } return GuidHob.Raw; }
/** Allocates one or more 4KB pages of a certain memory type. Allocates the number of 4KB pages of a certain memory type and returns a pointer to the allocated buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL is returned. If there is not enough memory remaining to satisfy the request, then NULL is returned. @param MemoryType The type of memory to allocate. @param Pages The number of 4 KB pages to allocate. @return A pointer to the allocated buffer or NULL if allocation fails. **/ VOID * InternalAllocatePages ( IN EFI_MEMORY_TYPE MemoryType, IN UINTN Pages ) { EFI_STATUS Status; EFI_PHYSICAL_ADDRESS Memory; EFI_MEMORY_TYPE RequestType; EFI_PEI_HOB_POINTERS Hob; if (Pages == 0) { return NULL; } RequestType = MemoryType; if (MemoryType == EfiReservedMemoryType) { // // PEI AllocatePages() doesn't support EfiReservedMemoryType. // Change RequestType to EfiBootServicesData for memory allocation. // RequestType = EfiBootServicesData; } Status = PeiServicesAllocatePages (RequestType, Pages, &Memory); if (EFI_ERROR (Status)) { return NULL; } if (MemoryType == EfiReservedMemoryType) { // // Memory type needs to be updated to EfiReservedMemoryType. Per PI spec Volume 1, // PEI AllocatePages() will automate the creation of the Memory Allocation HOB types. // Search Memory Allocation HOB and find the matched memory region, // then change its memory type to EfiReservedMemoryType. // Hob.Raw = GetFirstHob (EFI_HOB_TYPE_MEMORY_ALLOCATION); while (Hob.Raw != NULL && Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress != Memory) { Hob.Raw = GET_NEXT_HOB (Hob); Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw); } ASSERT (Hob.Raw != NULL); Hob.MemoryAllocation->AllocDescriptor.MemoryType = EfiReservedMemoryType; } return (VOID *) (UINTN) Memory; }
/** Register DXE Core to memory profile. @param HobStart The start address of the HOB. @param ContextData Memory profile context. @retval TRUE Register success. @retval FALSE Register fail. **/ BOOLEAN RegisterDxeCore ( IN VOID *HobStart, IN MEMORY_PROFILE_CONTEXT_DATA *ContextData ) { EFI_PEI_HOB_POINTERS DxeCoreHob; MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData; PHYSICAL_ADDRESS ImageBase; ASSERT (ContextData != NULL); // // Searching for image hob // DxeCoreHob.Raw = HobStart; while ((DxeCoreHob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, DxeCoreHob.Raw)) != NULL) { if (CompareGuid (&DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.Name, &gEfiHobMemoryAllocModuleGuid)) { // // Find Dxe Core HOB // break; } DxeCoreHob.Raw = GET_NEXT_HOB (DxeCoreHob); } ASSERT (DxeCoreHob.Raw != NULL); ImageBase = DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.MemoryBaseAddress; DriverInfoData = BuildDriverInfo ( ContextData, &DxeCoreHob.MemoryAllocationModule->ModuleName, ImageBase, DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.MemoryLength, DxeCoreHob.MemoryAllocationModule->EntryPoint, InternalPeCoffGetSubsystem ((VOID *) (UINTN) ImageBase), EFI_FV_FILETYPE_DXE_CORE ); if (DriverInfoData == NULL) { return FALSE; } return TRUE; }
VOID CreatePlatformSmbiosMemoryRecords ( VOID ) { EFI_PEI_HOB_POINTERS HobPtr; SMBIOS_STRUCTURE_POINTER Smbios16; SMBIOS_STRUCTURE_POINTER Smbios17; EFI_SMBIOS_HANDLE PhyscialMemoryArrayHandle; EFI_SMBIOS_HANDLE SmbiosHandle; Smbios16.Hdr = SmbiosLibGetRecord (EFI_SMBIOS_TYPE_PHYSICAL_MEMORY_ARRAY, 0, &PhyscialMemoryArrayHandle); if (Smbios16.Hdr == NULL) { // Only make a Type19 entry if a Type16 entry exists. return; } Smbios17.Hdr = SmbiosLibGetRecord (EFI_SMBIOS_TYPE_MEMORY_DEVICE, 0, &SmbiosHandle); if (Smbios17.Hdr == NULL) { // if type17 exits update with type16 Smbios handle Smbios17.Type17->MemoryArrayHandle = PhyscialMemoryArrayHandle; } // Generate Type16 records gSmbiosType19Template.MemoryArrayHandle = PhyscialMemoryArrayHandle; HobPtr.Raw = GetHobList (); while ((HobPtr.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, HobPtr.Raw)) != NULL) { if (HobPtr.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) { gSmbiosType19Template.ExtendedStartingAddress = HobPtr.ResourceDescriptor->PhysicalStart; gSmbiosType19Template.ExtendedEndingAddress = HobPtr.ResourceDescriptor->PhysicalStart + HobPtr.ResourceDescriptor->ResourceLength - 1; SmbiosLibCreateEntry ((SMBIOS_STRUCTURE *)&gSmbiosType19Template, NULL); } HobPtr.Raw = GET_NEXT_HOB (HobPtr); } }
/*++ Routine Description: Arguments: FileHandle - Handle of the file being invoked. PeiServices - Describes the list of possible PEI Services. Returns: Status - EFI_SUCCESS if the boot mode could be set --*/ EFI_STATUS EFIAPI MemoryPeim ( IN EFI_PHYSICAL_ADDRESS UefiMemoryBase, IN UINT64 UefiMemorySize ) { EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttributes; UINT64 ResourceLength; EFI_PEI_HOB_POINTERS NextHob; EFI_PHYSICAL_ADDRESS FdTop; EFI_PHYSICAL_ADDRESS SystemMemoryTop; EFI_PHYSICAL_ADDRESS ResourceTop; BOOLEAN Found; // Ensure PcdSystemMemorySize has been set ASSERT (PcdGet32 (PcdSystemMemorySize) != 0); // // Now, the permanent memory has been installed, we can call AllocatePages() // ResourceAttributes = ( EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED | EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE | EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE | EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE | EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE | EFI_RESOURCE_ATTRIBUTE_TESTED ); // Reserved the memory space occupied by the firmware volume BuildResourceDescriptorHob ( EFI_RESOURCE_SYSTEM_MEMORY, ResourceAttributes, PcdGet32 (PcdSystemMemoryBase), PcdGet32 (PcdSystemMemorySize) ); SystemMemoryTop = PcdGet32 (PcdSystemMemoryBase) + PcdGet32 (PcdSystemMemorySize); FdTop = PcdGet32(PcdFdBaseAddress) + PcdGet32(PcdFdSize); // EDK2 does not have the concept of boot firmware copied into DRAM. To avoid the DXE // core to overwrite this area we must mark the region with the attribute non-present if ((PcdGet32 (PcdFdBaseAddress) >= PcdGet32 (PcdSystemMemoryBase)) && (FdTop <= SystemMemoryTop)) { Found = FALSE; // Search for System Memory Hob that contains the firmware NextHob.Raw = GetHobList (); while ((NextHob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, NextHob.Raw)) != NULL) { if ((NextHob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) && (PcdGet32(PcdFdBaseAddress) >= NextHob.ResourceDescriptor->PhysicalStart) && (FdTop <= NextHob.ResourceDescriptor->PhysicalStart + NextHob.ResourceDescriptor->ResourceLength)) { ResourceAttributes = NextHob.ResourceDescriptor->ResourceAttribute; ResourceLength = NextHob.ResourceDescriptor->ResourceLength; ResourceTop = NextHob.ResourceDescriptor->PhysicalStart + ResourceLength; if (PcdGet32(PcdFdBaseAddress) == NextHob.ResourceDescriptor->PhysicalStart) { if (SystemMemoryTop == FdTop) { NextHob.ResourceDescriptor->ResourceAttribute = ResourceAttributes & ~EFI_RESOURCE_ATTRIBUTE_PRESENT; } else { // Create the System Memory HOB for the firmware with the non-present attribute BuildResourceDescriptorHob (EFI_RESOURCE_SYSTEM_MEMORY, ResourceAttributes & ~EFI_RESOURCE_ATTRIBUTE_PRESENT, PcdGet32(PcdFdBaseAddress), PcdGet32(PcdFdSize)); // Top of the FD is system memory available for UEFI NextHob.ResourceDescriptor->PhysicalStart += PcdGet32(PcdFdSize); NextHob.ResourceDescriptor->ResourceLength -= PcdGet32(PcdFdSize); } } else { // Create the System Memory HOB for the firmware with the non-present attribute BuildResourceDescriptorHob (EFI_RESOURCE_SYSTEM_MEMORY, ResourceAttributes & ~EFI_RESOURCE_ATTRIBUTE_PRESENT, PcdGet32(PcdFdBaseAddress), PcdGet32(PcdFdSize)); // Update the HOB NextHob.ResourceDescriptor->ResourceLength = PcdGet32(PcdFdBaseAddress) - NextHob.ResourceDescriptor->PhysicalStart; // If there is some memory available on the top of the FD then create a HOB if (FdTop < NextHob.ResourceDescriptor->PhysicalStart + ResourceLength) { // Create the System Memory HOB for the remaining region (top of the FD) BuildResourceDescriptorHob (EFI_RESOURCE_SYSTEM_MEMORY, ResourceAttributes, FdTop, ResourceTop - FdTop); } } Found = TRUE; break; } NextHob.Raw = GET_NEXT_HOB (NextHob); } ASSERT(Found); } // Build Memory Allocation Hob InitMmu (); if (FeaturePcdGet (PcdPrePiProduceMemoryTypeInformationHob)) { // Optional feature that helps prevent EFI memory map fragmentation. BuildMemoryTypeInformationHob (); } return EFI_SUCCESS; }
/** BIOS process FspBobList for Memory Resource Descriptor. @param[in] FspHobList Pointer to the HOB data structure produced by FSP. @return If platform process the FSP hob list successfully. **/ EFI_STATUS EFIAPI FspHobProcessForMemoryResource ( IN VOID *FspHobList ) { EFI_PEI_HOB_POINTERS Hob; UINT64 LowMemorySize; UINT64 FspMemorySize; EFI_PHYSICAL_ADDRESS FspMemoryBase; UINT64 PeiMemSize; EFI_PHYSICAL_ADDRESS PeiMemBase; UINT64 S3PeiMemSize; EFI_PHYSICAL_ADDRESS S3PeiMemBase; BOOLEAN FoundFspMemHob; EFI_STATUS Status; EFI_BOOT_MODE BootMode; PEI_CAPSULE_PPI *Capsule; VOID *CapsuleBuffer; UINTN CapsuleBufferLength; UINT64 RequiredMemSize; EFI_PEI_SERVICES **PeiServices; PeiServices = (EFI_PEI_SERVICES **)GetPeiServicesTablePointer (); PeiServicesGetBootMode (&BootMode); PeiMemBase = 0; LowMemorySize = 0; FspMemorySize = 0; FspMemoryBase = 0; FoundFspMemHob = FALSE; // // Parse the hob list from fsp // Report all the resource hob except the memory between 1M and 4G // Hob.Raw = (UINT8 *)(UINTN)FspHobList; DEBUG((DEBUG_INFO, "FspHobList - 0x%x\n", FspHobList)); while ((Hob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, Hob.Raw)) != NULL) { DEBUG((DEBUG_INFO, "\nResourceType: 0x%x\n", Hob.ResourceDescriptor->ResourceType)); if ((Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) || (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_MEMORY_RESERVED)) { DEBUG((DEBUG_INFO, "ResourceAttribute: 0x%x\n", Hob.ResourceDescriptor->ResourceAttribute)); DEBUG((DEBUG_INFO, "PhysicalStart: 0x%x\n", Hob.ResourceDescriptor->PhysicalStart)); DEBUG((DEBUG_INFO, "ResourceLength: 0x%x\n", Hob.ResourceDescriptor->ResourceLength)); DEBUG((DEBUG_INFO, "Owner: %g\n\n", &Hob.ResourceDescriptor->Owner)); } if ((Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) // Found the low memory length below 4G && (Hob.ResourceDescriptor->PhysicalStart >= BASE_1MB) && (Hob.ResourceDescriptor->PhysicalStart + Hob.ResourceDescriptor->ResourceLength <= BASE_4GB)) { LowMemorySize += Hob.ResourceDescriptor->ResourceLength; Hob.Raw = GET_NEXT_HOB (Hob); continue; } if ((Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_MEMORY_RESERVED) // Found the low memory length below 4G && (Hob.ResourceDescriptor->PhysicalStart >= BASE_1MB) && (Hob.ResourceDescriptor->PhysicalStart + Hob.ResourceDescriptor->ResourceLength <= BASE_4GB) && (CompareGuid (&Hob.ResourceDescriptor->Owner, &gFspReservedMemoryResourceHobGuid))) { FoundFspMemHob = TRUE; FspMemoryBase = Hob.ResourceDescriptor->PhysicalStart; FspMemorySize = Hob.ResourceDescriptor->ResourceLength; DEBUG((DEBUG_INFO, "Find fsp mem hob, base 0x%x, len 0x%x\n", FspMemoryBase, FspMemorySize)); } // // Report the resource hob // BuildResourceDescriptorHob ( Hob.ResourceDescriptor->ResourceType, Hob.ResourceDescriptor->ResourceAttribute, Hob.ResourceDescriptor->PhysicalStart, Hob.ResourceDescriptor->ResourceLength ); Hob.Raw = GET_NEXT_HOB (Hob); } if (!FoundFspMemHob) { DEBUG((DEBUG_INFO, "Didn't find the fsp used memory information.\n")); //ASSERT(FALSE); } DEBUG((DEBUG_INFO, "LowMemorySize: 0x%x.\n", LowMemorySize)); DEBUG((DEBUG_INFO, "FspMemoryBase: 0x%x.\n", FspMemoryBase)); DEBUG((DEBUG_INFO, "FspMemorySize: 0x%x.\n", FspMemorySize)); if (BootMode == BOOT_ON_S3_RESUME) { BuildResourceDescriptorHob ( EFI_RESOURCE_SYSTEM_MEMORY, ( EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED | // EFI_RESOURCE_ATTRIBUTE_TESTED | EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE | EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE | EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE | EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE ), BASE_1MB, LowMemorySize ); S3PeiMemBase = 0; S3PeiMemSize = 0; Status = GetS3MemoryInfo (&S3PeiMemBase, &S3PeiMemSize); ASSERT_EFI_ERROR (Status); DEBUG((DEBUG_INFO, "S3 memory %Xh - %Xh bytes\n", S3PeiMemBase, S3PeiMemSize)); // // Make sure Stack and PeiMemory are not overlap // Status = PeiServicesInstallPeiMemory ( S3PeiMemBase, S3PeiMemSize ); ASSERT_EFI_ERROR (Status); } else { PeiMemSize = GetPeiMemSize (PeiServices, BootMode); DEBUG((DEBUG_INFO, "PEI memory size = %Xh bytes\n", PeiMemSize)); // // Capsule mode // Capsule = NULL; CapsuleBuffer = NULL; CapsuleBufferLength = 0; if (BootMode == BOOT_ON_FLASH_UPDATE) { Status = PeiServicesLocatePpi ( &gPeiCapsulePpiGuid, 0, NULL, (VOID **) &Capsule ); ASSERT_EFI_ERROR (Status); if (Status == EFI_SUCCESS) { // // Make sure Stack and CapsuleBuffer are not overlap // CapsuleBuffer = (VOID *)(UINTN)BASE_1MB; CapsuleBufferLength = (UINTN)(LowMemorySize - PeiMemSize); // // Call the Capsule PPI Coalesce function to coalesce the capsule data. // Status = Capsule->Coalesce (PeiServices, &CapsuleBuffer, &CapsuleBufferLength); } } RequiredMemSize = RetrieveRequiredMemorySize (PeiServices); DEBUG((DEBUG_INFO, "Required memory size = %Xh bytes\n", RequiredMemSize)); // // Report the main memory // BuildResourceDescriptorHob ( EFI_RESOURCE_SYSTEM_MEMORY, ( EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED | EFI_RESOURCE_ATTRIBUTE_TESTED | EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE | EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE | EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE | EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE ), BASE_1MB, LowMemorySize ); // // Make sure Stack and CapsuleBuffer are not overlap // // // Install efi memory // PeiMemBase = BASE_1MB + LowMemorySize - PeiMemSize; Status = PeiServicesInstallPeiMemory ( PeiMemBase, PeiMemSize - RequiredMemSize ); ASSERT_EFI_ERROR (Status); if (Capsule != NULL) { Status = Capsule->CreateState (PeiServices, CapsuleBuffer, CapsuleBufferLength); } } return EFI_SUCCESS; }
/** This routine is called to see if there are any capsules we need to process. If the boot mode is not UPDATE, then we do nothing. Otherwise find the capsule HOBS and produce firmware volumes for them via the DXE service. Then call the dispatcher to dispatch drivers from them. Finally, check the status of the updates. This function should be called by BDS in case we need to do some sort of processing even if there is no capsule to process. We need to do this if an earlier update went away and we need to clear the capsule variable so on the next reset PEI does not see it and think there is a capsule available. @param BootMode the current boot mode @retval EFI_INVALID_PARAMETER boot mode is not correct for an update @retval EFI_SUCCESS There is no error when processing capsule **/ EFI_STATUS EFIAPI BdsProcessCapsules ( EFI_BOOT_MODE BootMode ) { EFI_STATUS Status; EFI_PEI_HOB_POINTERS HobPointer; EFI_CAPSULE_HEADER *CapsuleHeader; UINT32 Size; UINT32 CapsuleNumber; UINT32 CapsuleTotalNumber; EFI_CAPSULE_TABLE *CapsuleTable; UINT32 Index; UINT32 CacheIndex; UINT32 CacheNumber; VOID **CapsulePtr; VOID **CapsulePtrCache; EFI_GUID *CapsuleGuidCache; BOOLEAN NeedReset; CapsuleNumber = 0; CapsuleTotalNumber = 0; CacheIndex = 0; CacheNumber = 0; CapsulePtr = NULL; CapsulePtrCache = NULL; CapsuleGuidCache = NULL; NeedReset = FALSE; // // We don't do anything else if the boot mode is not flash-update // if (BootMode != BOOT_ON_FLASH_UPDATE) { DEBUG ((EFI_D_ERROR, "Boot mode is not correct for capsule update.\n")); return EFI_INVALID_PARAMETER; } Status = EFI_SUCCESS; // // Find all capsule images from hob // HobPointer.Raw = GetHobList (); while ((HobPointer.Raw = GetNextHob (EFI_HOB_TYPE_UEFI_CAPSULE, HobPointer.Raw)) != NULL) { CapsuleTotalNumber ++; HobPointer.Raw = GET_NEXT_HOB (HobPointer); } if (CapsuleTotalNumber == 0) { // // We didn't find a hob, so had no errors. // DEBUG ((EFI_D_ERROR, "We can not find capsule data in capsule update boot mode.\n")); DEBUG ((EFI_D_ERROR, "Please check the followings are correct if unexpected capsule update error happens.\n")); DEBUG ((EFI_D_ERROR, "1. CapsuleX64 is built as X64 module when PEI is IA32 and DXE is X64\n")); DEBUG ((EFI_D_ERROR, "2. Capsule data should persist in memory across a system reset.\n")); PlatformBdsLockNonUpdatableFlash (); return EFI_SUCCESS; } // // Init temp Capsule Data table. // CapsulePtr = (VOID **) AllocateZeroPool (sizeof (VOID *) * CapsuleTotalNumber); ASSERT (CapsulePtr != NULL); CapsulePtrCache = (VOID **) AllocateZeroPool (sizeof (VOID *) * CapsuleTotalNumber); ASSERT (CapsulePtrCache != NULL); CapsuleGuidCache = (EFI_GUID *) AllocateZeroPool (sizeof (EFI_GUID) * CapsuleTotalNumber); ASSERT (CapsuleGuidCache != NULL); // // Find all capsule images from hob // HobPointer.Raw = GetHobList (); while ((HobPointer.Raw = GetNextHob (EFI_HOB_TYPE_UEFI_CAPSULE, HobPointer.Raw)) != NULL) { CapsulePtr [CapsuleNumber++] = (VOID *) (UINTN) HobPointer.Capsule->BaseAddress; HobPointer.Raw = GET_NEXT_HOB (HobPointer); } // //Check the capsule flags,if contains CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE, install //capsuleTable to configure table with EFI_CAPSULE_GUID // // // Capsules who have CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE always are used for operating // System to have information persist across a system reset. EFI System Table must // point to an array of capsules that contains the same CapsuleGuid value. And agents // searching for this type capsule will look in EFI System Table and search for the // capsule's Guid and associated pointer to retrieve the data. Two steps below describes // how to sorting the capsules by the unique guid and install the array to EFI System Table. // Firstly, Loop for all coalesced capsules, record unique CapsuleGuids and cache them in an // array for later sorting capsules by CapsuleGuid. // for (Index = 0; Index < CapsuleTotalNumber; Index++) { CapsuleHeader = (EFI_CAPSULE_HEADER*) CapsulePtr [Index]; if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) != 0) { // // For each capsule, we compare it with known CapsuleGuid in the CacheArray. // If already has the Guid, skip it. Whereas, record it in the CacheArray as // an additional one. // CacheIndex = 0; while (CacheIndex < CacheNumber) { if (CompareGuid(&CapsuleGuidCache[CacheIndex],&CapsuleHeader->CapsuleGuid)) { break; } CacheIndex++; } if (CacheIndex == CacheNumber) { CopyMem(&CapsuleGuidCache[CacheNumber++],&CapsuleHeader->CapsuleGuid,sizeof(EFI_GUID)); } } } // // Secondly, for each unique CapsuleGuid in CacheArray, gather all coalesced capsules // whose guid is the same as it, and malloc memory for an array which preceding // with UINT32. The array fills with entry point of capsules that have the same // CapsuleGuid, and UINT32 represents the size of the array of capsules. Then install // this array into EFI System Table, so that agents searching for this type capsule // will look in EFI System Table and search for the capsule's Guid and associated // pointer to retrieve the data. // CacheIndex = 0; while (CacheIndex < CacheNumber) { CapsuleNumber = 0; for (Index = 0; Index < CapsuleTotalNumber; Index++) { CapsuleHeader = (EFI_CAPSULE_HEADER*) CapsulePtr [Index]; if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) != 0) { if (CompareGuid (&CapsuleGuidCache[CacheIndex], &CapsuleHeader->CapsuleGuid)) { // // Cache Caspuleheader to the array, this array is uniqued with certain CapsuleGuid. // CapsulePtrCache[CapsuleNumber++] = (VOID*)CapsuleHeader; } } } if (CapsuleNumber != 0) { Size = sizeof(EFI_CAPSULE_TABLE) + (CapsuleNumber - 1) * sizeof(VOID*); CapsuleTable = AllocateRuntimePool (Size); ASSERT (CapsuleTable != NULL); CapsuleTable->CapsuleArrayNumber = CapsuleNumber; CopyMem(&CapsuleTable->CapsulePtr[0], CapsulePtrCache, CapsuleNumber * sizeof(VOID*)); Status = gBS->InstallConfigurationTable (&CapsuleGuidCache[CacheIndex], (VOID*)CapsuleTable); ASSERT_EFI_ERROR (Status); } CacheIndex++; } // // Besides ones with CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE flag, all capsules left are // recognized by platform with CapsuleGuid. For general platform driver, UpdateFlash // type is commonly supported, so here only deal with encapsuled FVs capsule. Additional // type capsule transaction could be extended. It depends on platform policy. // for (Index = 0; Index < CapsuleTotalNumber; Index++) { CapsuleHeader = (EFI_CAPSULE_HEADER*) CapsulePtr [Index]; if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) == 0) { // // Always reset system after all capsule processed if FMP capsule exist // if (CompareGuid (&gEfiFmpCapsuleGuid, &CapsuleHeader->CapsuleGuid)) { NeedReset = TRUE; } // // Call capsule library to process capsule image. // ProcessCapsuleImage (CapsuleHeader); } } if (NeedReset) { Print(L"Capsule Request Cold Reboot.\n"); for (Index = 5; Index > 0; Index--) { Print(L"\rResetting system in %d seconds ...", Index); gBS->Stall (1000000); } gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL); CpuDeadLoop (); } PlatformBdsLockNonUpdatableFlash (); // // Free the allocated temp memory space. // FreePool (CapsuleGuidCache); FreePool (CapsulePtrCache); FreePool (CapsulePtr); return Status; }
/** Allocates one or more 4KB pages of a certain memory type at a specified alignment. Allocates the number of 4KB pages specified by Pages of a certain memory type with an alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is returned. If there is not enough memory at the specified alignment remaining to satisfy the request, then NULL is returned. If Alignment is not a power of two and Alignment is not zero, then ASSERT(). If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT(). @param MemoryType The type of memory to allocate. @param Pages The number of 4 KB pages to allocate. @param Alignment The requested alignment of the allocation. Must be a power of two. If Alignment is zero, then byte alignment is used. @return A pointer to the allocated buffer or NULL if allocation fails. **/ VOID * InternalAllocateAlignedPages ( IN EFI_MEMORY_TYPE MemoryType, IN UINTN Pages, IN UINTN Alignment ) { EFI_PHYSICAL_ADDRESS Memory; EFI_PHYSICAL_ADDRESS AlignedMemory; EFI_PEI_HOB_POINTERS Hob; BOOLEAN SkipBeforeMemHob; BOOLEAN SkipAfterMemHob; EFI_PHYSICAL_ADDRESS HobBaseAddress; UINT64 HobLength; EFI_MEMORY_TYPE HobMemoryType; UINTN TotalPages; // // Alignment must be a power of two or zero. // ASSERT ((Alignment & (Alignment - 1)) == 0); if (Pages == 0) { return NULL; } // // Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow. // ASSERT (Pages <= (MAX_ADDRESS - EFI_SIZE_TO_PAGES (Alignment))); // // We would rather waste some memory to save PEI code size. // meaning in addition to the requested size for the aligned mem, // we simply reserve an overhead memory equal to Alignmemt(page-aligned), no matter what. // The overhead mem size could be reduced later with more involved malloc mechanisms // (e.g., somthing that can detect the alignment boundary before allocating memory or // can request that memory be allocated at a certain address that is aleady aligned). // TotalPages = Pages + (Alignment <= EFI_PAGE_SIZE ? 0 : EFI_SIZE_TO_PAGES(Alignment)); Memory = (EFI_PHYSICAL_ADDRESS) (UINTN) InternalAllocatePages (MemoryType, TotalPages); if (Memory == 0) { DEBUG((DEBUG_INFO, "Out of memory resource! \n")); return NULL; } DEBUG ((DEBUG_INFO, "Allocated Memory unaligned: Address = 0x%LX, Pages = 0x%X, Type = %d \n", Memory, TotalPages, (UINTN) MemoryType)); // // Alignment calculation // AlignedMemory = Memory; if (Alignment > EFI_PAGE_SIZE) { AlignedMemory = ALIGN_VALUE (Memory, Alignment); } DEBUG ((DEBUG_INFO, "After aligning to 0x%X bytes: Address = 0x%LX, Pages = 0x%X \n", Alignment, AlignedMemory, Pages)); // // In general three HOBs cover the total allocated space. // The aligned portion is covered by the aligned mem HOB and // the unaligned(to be freed) portions before and after the aligned portion are covered by newly created HOBs. // // Before mem HOB covers the region between "Memory" and "AlignedMemory" // Aligned mem HOB covers the region between "AlignedMemory" and "AlignedMemory + EFI_PAGES_TO_SIZE(Pages)" // After mem HOB covers the region between "AlignedMemory + EFI_PAGES_TO_SIZE(Pages)" and "Memory + EFI_PAGES_TO_SIZE(TotalPages)" // // The before or after mem HOBs need to be skipped under special cases where the aligned portion // touches either the top or bottom of the original allocated space. // SkipBeforeMemHob = FALSE; SkipAfterMemHob = FALSE; if (Memory == AlignedMemory) { SkipBeforeMemHob = TRUE; } if ((Memory + EFI_PAGES_TO_SIZE(TotalPages)) == (AlignedMemory + EFI_PAGES_TO_SIZE(Pages))) { // // This condition is never met in the current implementation. // There is always some after-mem since the overhead mem(used in TotalPages) // is no less than Alignment. // SkipAfterMemHob = TRUE; } // // Search for the mem HOB referring to the original(unaligned) allocation // and update the size and type if needed. // Hob.Raw = GetFirstHob (EFI_HOB_TYPE_MEMORY_ALLOCATION); while (Hob.Raw != NULL) { if (Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress == Memory) { break; } Hob.Raw = GET_NEXT_HOB (Hob); Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw); } ASSERT (Hob.Raw != NULL); if (SkipBeforeMemHob) { // // Use this HOB as aligned mem HOB as there is no portion before it. // HobLength = EFI_PAGES_TO_SIZE(Pages); Hob.MemoryAllocation->AllocDescriptor.MemoryLength = HobLength; } else { // // Use this HOB as before mem HOB and create a new HOB for the aligned portion // HobLength = (AlignedMemory - Memory); Hob.MemoryAllocation->AllocDescriptor.MemoryLength = HobLength; Hob.MemoryAllocation->AllocDescriptor.MemoryType = EfiConventionalMemory; } HobBaseAddress = Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress; HobMemoryType = Hob.MemoryAllocation->AllocDescriptor.MemoryType; // // Build the aligned mem HOB if needed // if (!SkipBeforeMemHob) { DEBUG((DEBUG_INFO, "Updated before-mem HOB with BaseAddress = %LX, Length = %LX, MemoryType = %d \n", HobBaseAddress, HobLength, (UINTN) HobMemoryType)); HobBaseAddress = AlignedMemory; HobLength = EFI_PAGES_TO_SIZE(Pages); HobMemoryType = MemoryType; BuildMemoryAllocationHob ( HobBaseAddress, HobLength, HobMemoryType ); DEBUG((DEBUG_INFO, "Created aligned-mem HOB with BaseAddress = %LX, Length = %LX, MemoryType = %d \n", HobBaseAddress, HobLength, (UINTN) HobMemoryType)); } else { if (HobBaseAddress != 0) { DEBUG((DEBUG_INFO, "Updated aligned-mem HOB with BaseAddress = %LX, Length = %LX, MemoryType = %d \n", HobBaseAddress, HobLength, (UINTN) HobMemoryType)); } } // // Build the after mem HOB if needed // if (!SkipAfterMemHob) { HobBaseAddress = AlignedMemory + EFI_PAGES_TO_SIZE(Pages); HobLength = (Memory + EFI_PAGES_TO_SIZE(TotalPages)) - (AlignedMemory + EFI_PAGES_TO_SIZE(Pages)); HobMemoryType = EfiConventionalMemory; BuildMemoryAllocationHob ( HobBaseAddress, HobLength, HobMemoryType ); DEBUG((DEBUG_INFO, "Created after-mem HOB with BaseAddress = %LX, Length = %LX, MemoryType = %d \n", HobBaseAddress, HobLength, (UINTN) HobMemoryType)); } return (VOID *) (UINTN) AlignedMemory; }
/** Remove exec permissions from all regions whose type is identified by PcdDxeNxMemoryProtectionPolicy. **/ STATIC VOID InitializeDxeNxMemoryProtectionPolicy ( VOID ) { UINTN MemoryMapSize; UINTN MapKey; UINTN DescriptorSize; UINT32 DescriptorVersion; EFI_MEMORY_DESCRIPTOR *MemoryMap; EFI_MEMORY_DESCRIPTOR *MemoryMapEntry; EFI_MEMORY_DESCRIPTOR *MemoryMapEnd; EFI_STATUS Status; UINT64 Attributes; LIST_ENTRY *Link; EFI_GCD_MAP_ENTRY *Entry; EFI_PEI_HOB_POINTERS Hob; EFI_HOB_MEMORY_ALLOCATION *MemoryHob; EFI_PHYSICAL_ADDRESS StackBase; // // Get the EFI memory map. // MemoryMapSize = 0; MemoryMap = NULL; Status = gBS->GetMemoryMap ( &MemoryMapSize, MemoryMap, &MapKey, &DescriptorSize, &DescriptorVersion ); ASSERT (Status == EFI_BUFFER_TOO_SMALL); do { MemoryMap = (EFI_MEMORY_DESCRIPTOR *) AllocatePool (MemoryMapSize); ASSERT (MemoryMap != NULL); Status = gBS->GetMemoryMap ( &MemoryMapSize, MemoryMap, &MapKey, &DescriptorSize, &DescriptorVersion ); if (EFI_ERROR (Status)) { FreePool (MemoryMap); } } while (Status == EFI_BUFFER_TOO_SMALL); ASSERT_EFI_ERROR (Status); StackBase = 0; if (PcdGetBool (PcdCpuStackGuard)) { // // Get the base of stack from Hob. // Hob.Raw = GetHobList (); while ((Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw)) != NULL) { MemoryHob = Hob.MemoryAllocation; if (CompareGuid(&gEfiHobMemoryAllocStackGuid, &MemoryHob->AllocDescriptor.Name)) { DEBUG (( DEBUG_INFO, "%a: StackBase = 0x%016lx StackSize = 0x%016lx\n", __FUNCTION__, MemoryHob->AllocDescriptor.MemoryBaseAddress, MemoryHob->AllocDescriptor.MemoryLength )); StackBase = MemoryHob->AllocDescriptor.MemoryBaseAddress; // // Ensure the base of the stack is page-size aligned. // ASSERT ((StackBase & EFI_PAGE_MASK) == 0); break; } Hob.Raw = GET_NEXT_HOB (Hob); } // // Ensure the base of stack can be found from Hob when stack guard is // enabled. // ASSERT (StackBase != 0); } DEBUG (( DEBUG_INFO, "%a: applying strict permissions to active memory regions\n", __FUNCTION__ )); MergeMemoryMapForProtectionPolicy (MemoryMap, &MemoryMapSize, DescriptorSize); MemoryMapEntry = MemoryMap; MemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) MemoryMap + MemoryMapSize); while ((UINTN) MemoryMapEntry < (UINTN) MemoryMapEnd) { Attributes = GetPermissionAttributeForMemoryType (MemoryMapEntry->Type); if (Attributes != 0) { SetUefiImageMemoryAttributes ( MemoryMapEntry->PhysicalStart, LShiftU64 (MemoryMapEntry->NumberOfPages, EFI_PAGE_SHIFT), Attributes); // // Add EFI_MEMORY_RP attribute for page 0 if NULL pointer detection is // enabled. // if (MemoryMapEntry->PhysicalStart == 0 && PcdGet8 (PcdNullPointerDetectionPropertyMask) != 0) { ASSERT (MemoryMapEntry->NumberOfPages > 0); SetUefiImageMemoryAttributes ( 0, EFI_PAGES_TO_SIZE (1), EFI_MEMORY_RP | Attributes); } // // Add EFI_MEMORY_RP attribute for the first page of the stack if stack // guard is enabled. // if (StackBase != 0 && (StackBase >= MemoryMapEntry->PhysicalStart && StackBase < MemoryMapEntry->PhysicalStart + LShiftU64 (MemoryMapEntry->NumberOfPages, EFI_PAGE_SHIFT)) && PcdGetBool (PcdCpuStackGuard)) { SetUefiImageMemoryAttributes ( StackBase, EFI_PAGES_TO_SIZE (1), EFI_MEMORY_RP | Attributes); } } MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize); } FreePool (MemoryMap); // // Apply the policy for RAM regions that we know are present and // accessible, but have not been added to the UEFI memory map (yet). // if (GetPermissionAttributeForMemoryType (EfiConventionalMemory) != 0) { DEBUG (( DEBUG_INFO, "%a: applying strict permissions to inactive memory regions\n", __FUNCTION__ )); CoreAcquireGcdMemoryLock (); Link = mGcdMemorySpaceMap.ForwardLink; while (Link != &mGcdMemorySpaceMap) { Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE); if (Entry->GcdMemoryType == EfiGcdMemoryTypeReserved && Entry->EndAddress < MAX_ADDRESS && (Entry->Capabilities & (EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED | EFI_MEMORY_TESTED)) == (EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED)) { Attributes = GetPermissionAttributeForMemoryType (EfiConventionalMemory) | (Entry->Attributes & CACHE_ATTRIBUTE_MASK); DEBUG ((DEBUG_INFO, "Untested GCD memory space region: - 0x%016lx - 0x%016lx (0x%016lx)\n", Entry->BaseAddress, Entry->EndAddress - Entry->BaseAddress + 1, Attributes)); ASSERT(gCpu != NULL); gCpu->SetMemoryAttributes (gCpu, Entry->BaseAddress, Entry->EndAddress - Entry->BaseAddress + 1, Attributes); } Link = Link->ForwardLink; } CoreReleaseGcdMemoryLock (); } }
EFI_STATUS EFIAPI FvbInitialize ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) /*++ Routine Description: This function does common initialization for FVB services Arguments: Returns: **/ { EFI_STATUS Status; EFI_FW_VOL_INSTANCE *FwhInstance = NULL; EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; EFI_DXE_SERVICES *DxeServices; EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor; UINT32 BufferSize; EFI_FV_BLOCK_MAP_ENTRY *PtrBlockMapEntry; EFI_HANDLE FwbHandle; EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *OldFwbInterface; EFI_DEVICE_PATH_PROTOCOL *TempFwbDevicePath; FV_DEVICE_PATH TempFvbDevicePathData; UINT32 MaxLbaSize; EFI_PHYSICAL_ADDRESS BaseAddress; UINT64 Length; UINTN NumOfBlocks; EFI_PEI_HOB_POINTERS FvHob; // // Get the DXE services table // DxeServices = gDS; // // Allocate runtime services data for global variable, which contains // the private data of all firmware volume block instances // Status = gBS->AllocatePool ( EfiRuntimeServicesData, sizeof (ESAL_FWB_GLOBAL), (VOID**) &mFvbModuleGlobal ); ASSERT_EFI_ERROR (Status); // // Calculate the total size for all firmware volume block instances // BufferSize = 0; FvHob.Raw = GetHobList (); while ((FvHob.Raw = GetNextHob (EFI_HOB_TYPE_FV, FvHob.Raw)) != NULL) { BaseAddress = FvHob.FirmwareVolume->BaseAddress; Length = FvHob.FirmwareVolume->Length; // // Check if it is a "real" flash // Status = DxeServices->GetMemorySpaceDescriptor ( BaseAddress, &Descriptor ); if (EFI_ERROR (Status)) { break; } if (Descriptor.GcdMemoryType != EfiGcdMemoryTypeMemoryMappedIo) { FvHob.Raw = GET_NEXT_HOB (FvHob); continue; } FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) BaseAddress; Status = ValidateFvHeader (FwVolHeader); if (EFI_ERROR (Status)) { // // Get FvbInfo // Status = GetFvbInfo (Length, &FwVolHeader); if (EFI_ERROR (Status)) { FvHob.Raw = GET_NEXT_HOB (FvHob); continue; } } BufferSize += (sizeof (EFI_FW_VOL_INSTANCE) + FwVolHeader->HeaderLength - sizeof (EFI_FIRMWARE_VOLUME_HEADER)); FvHob.Raw = GET_NEXT_HOB (FvHob); } // // Only need to allocate once. There is only one copy of physical memory for // the private data of each FV instance. But in virtual mode or in physical // mode, the address of the the physical memory may be different. // Status = gBS->AllocatePool ( EfiRuntimeServicesData, BufferSize, (VOID**) &mFvbModuleGlobal->FvInstance[FVB_PHYSICAL] ); ASSERT_EFI_ERROR (Status); // // Make a virtual copy of the FvInstance pointer. // FwhInstance = mFvbModuleGlobal->FvInstance[FVB_PHYSICAL]; mFvbModuleGlobal->FvInstance[FVB_VIRTUAL] = FwhInstance; mFvbModuleGlobal->NumFv = 0; MaxLbaSize = 0; FvHob.Raw = GetHobList (); while (NULL != (FvHob.Raw = GetNextHob (EFI_HOB_TYPE_FV, FvHob.Raw))) { BaseAddress = FvHob.FirmwareVolume->BaseAddress; Length = FvHob.FirmwareVolume->Length; // // Check if it is a "real" flash // Status = DxeServices->GetMemorySpaceDescriptor ( BaseAddress, &Descriptor ); if (EFI_ERROR (Status)) { break; } if (Descriptor.GcdMemoryType != EfiGcdMemoryTypeMemoryMappedIo) { FvHob.Raw = GET_NEXT_HOB (FvHob); continue; } FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) BaseAddress; Status = ValidateFvHeader (FwVolHeader); if (EFI_ERROR (Status)) { // // Get FvbInfo to provide in FwhInstance. // Status = GetFvbInfo (Length, &FwVolHeader); if (EFI_ERROR (Status)) { FvHob.Raw = GET_NEXT_HOB (FvHob); continue; } // // Write healthy FV header back. // CopyMem ( (VOID *) (UINTN) BaseAddress, (VOID *) FwVolHeader, FwVolHeader->HeaderLength ); } FwhInstance->FvBase[FVB_PHYSICAL] = (UINTN) BaseAddress; FwhInstance->FvBase[FVB_VIRTUAL] = (UINTN) BaseAddress; CopyMem ((UINTN *) &(FwhInstance->VolumeHeader), (UINTN *) FwVolHeader, FwVolHeader->HeaderLength); FwVolHeader = &(FwhInstance->VolumeHeader); EfiInitializeLock (&(FwhInstance->FvbDevLock), TPL_HIGH_LEVEL); NumOfBlocks = 0; for (PtrBlockMapEntry = FwVolHeader->BlockMap; PtrBlockMapEntry->NumBlocks != 0; PtrBlockMapEntry++) { // // Get the maximum size of a block. The size will be used to allocate // buffer for Scratch space, the intermediate buffer for FVB extension // protocol // if (MaxLbaSize < PtrBlockMapEntry->Length) { MaxLbaSize = PtrBlockMapEntry->Length; } NumOfBlocks = NumOfBlocks + PtrBlockMapEntry->NumBlocks; } // // The total number of blocks in the FV. // FwhInstance->NumOfBlocks = NumOfBlocks; // // Add a FVB Protocol Instance // Status = gBS->AllocatePool ( EfiRuntimeServicesData, sizeof (EFI_FW_VOL_BLOCK_DEVICE), (VOID**) &FvbDevice ); ASSERT_EFI_ERROR (Status); CopyMem (FvbDevice, &mFvbDeviceTemplate, sizeof (EFI_FW_VOL_BLOCK_DEVICE)); FvbDevice->Instance = mFvbModuleGlobal->NumFv; mFvbModuleGlobal->NumFv++; // // Set up the devicepath // FvbDevice->DevicePath.MemMapDevPath.StartingAddress = BaseAddress; FvbDevice->DevicePath.MemMapDevPath.EndingAddress = BaseAddress + (FwVolHeader->FvLength - 1); // // Find a handle with a matching device path that has supports FW Block protocol // TempFwbDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) &TempFvbDevicePathData; CopyMem (TempFwbDevicePath, &FvbDevice->DevicePath, sizeof (FV_DEVICE_PATH)); Status = gBS->LocateDevicePath (&gEfiFirmwareVolumeBlockProtocolGuid, &TempFwbDevicePath, &FwbHandle); if (EFI_ERROR (Status)) { // // LocateDevicePath fails so install a new interface and device path // FwbHandle = NULL; Status = gBS->InstallMultipleProtocolInterfaces ( &FwbHandle, &gEfiFirmwareVolumeBlockProtocolGuid, &FvbDevice->FwVolBlockInstance, &gEfiDevicePathProtocolGuid, &FvbDevice->DevicePath, NULL ); ASSERT_EFI_ERROR (Status); } else if (IsDevicePathEnd (TempFwbDevicePath)) { // // Device allready exists, so reinstall the FVB protocol // Status = gBS->HandleProtocol ( FwbHandle, &gEfiFirmwareVolumeBlockProtocolGuid, (VOID**)&OldFwbInterface ); ASSERT_EFI_ERROR (Status); Status = gBS->ReinstallProtocolInterface ( FwbHandle, &gEfiFirmwareVolumeBlockProtocolGuid, OldFwbInterface, &FvbDevice->FwVolBlockInstance ); ASSERT_EFI_ERROR (Status); } else { // // There was a FVB protocol on an End Device Path node // ASSERT (FALSE); } FwhInstance = (EFI_FW_VOL_INSTANCE *) ( (UINTN) ((UINT8 *) FwhInstance) + FwVolHeader->HeaderLength + (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER)) ); FvHob.Raw = GET_NEXT_HOB (FvHob); } return EFI_SUCCESS; }
/** Build guid hob for the global memory to store the registered guid and Handler list. If GuidHob exists, HandlerInfo will be directly got from Guid hob data. @param[in, out] InfoPointer The pointer to pei handler information structure. @retval RETURN_SUCCESS Build Guid hob for the global memory space to store guid and function tables. @retval RETURN_OUT_OF_RESOURCES No enough memory to allocated. **/ RETURN_STATUS PeiGetExtractGuidedSectionHandlerInfo ( IN OUT PEI_EXTRACT_GUIDED_SECTION_HANDLER_INFO **InfoPointer ) { PEI_EXTRACT_GUIDED_SECTION_HANDLER_INFO *HandlerInfo; EFI_PEI_HOB_POINTERS Hob; // // First try to get handler information from guid hob specified by CallerId. // Hob.Raw = GetNextHob (EFI_HOB_TYPE_GUID_EXTENSION, GetHobList ()); while (Hob.Raw != NULL) { if (CompareGuid (&(Hob.Guid->Name), &gEfiCallerIdGuid)) { HandlerInfo = (PEI_EXTRACT_GUIDED_SECTION_HANDLER_INFO *) GET_GUID_HOB_DATA (Hob.Guid); if (HandlerInfo->Signature == PEI_EXTRACT_HANDLER_INFO_SIGNATURE) { // // Update Table Pointer when hob start address is changed. // if (HandlerInfo->ExtractHandlerGuidTable != (GUID *) (HandlerInfo + 1)) { HandlerInfo->ExtractHandlerGuidTable = (GUID *) (HandlerInfo + 1); HandlerInfo->ExtractDecodeHandlerTable = (EXTRACT_GUIDED_SECTION_DECODE_HANDLER *) ( (UINT8 *)HandlerInfo->ExtractHandlerGuidTable + PcdGet32 (PcdMaximumGuidedExtractHandler) * sizeof (GUID) ); HandlerInfo->ExtractGetInfoHandlerTable = (EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER *) ( (UINT8 *)HandlerInfo->ExtractDecodeHandlerTable + PcdGet32 (PcdMaximumGuidedExtractHandler) * sizeof (EXTRACT_GUIDED_SECTION_DECODE_HANDLER) ); } // // Return HandlerInfo pointer. // *InfoPointer = HandlerInfo; return EFI_SUCCESS; } } Hob.Raw = GET_NEXT_HOB (Hob); Hob.Raw = GetNextHob (EFI_HOB_TYPE_GUID_EXTENSION, Hob.Raw); } // // If Guid Hob is not found, Build CallerId Guid hob to store Handler Info // HandlerInfo = BuildGuidHob ( &gEfiCallerIdGuid, sizeof (PEI_EXTRACT_GUIDED_SECTION_HANDLER_INFO) + PcdGet32 (PcdMaximumGuidedExtractHandler) * (sizeof (GUID) + sizeof (EXTRACT_GUIDED_SECTION_DECODE_HANDLER) + sizeof (EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER)) ); if (HandlerInfo == NULL) { // // No enough resource to build guid hob. // *InfoPointer = NULL; return EFI_OUT_OF_RESOURCES; } // // Init HandlerInfo structure // HandlerInfo->Signature = PEI_EXTRACT_HANDLER_INFO_SIGNATURE; HandlerInfo->NumberOfExtractHandler = 0; HandlerInfo->ExtractHandlerGuidTable = (GUID *) (HandlerInfo + 1); HandlerInfo->ExtractDecodeHandlerTable = (EXTRACT_GUIDED_SECTION_DECODE_HANDLER *) ( (UINT8 *)HandlerInfo->ExtractHandlerGuidTable + PcdGet32 (PcdMaximumGuidedExtractHandler) * sizeof (GUID) ); HandlerInfo->ExtractGetInfoHandlerTable = (EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER *) ( (UINT8 *)HandlerInfo->ExtractDecodeHandlerTable + PcdGet32 (PcdMaximumGuidedExtractHandler) * sizeof (EXTRACT_GUIDED_SECTION_DECODE_HANDLER) ); // // return the created HandlerInfo. // *InfoPointer = HandlerInfo; return EFI_SUCCESS; }
/** Firmware volume inherits authentication status from the FV image file and section(in another firmware volume) where it came from or propagated from PEI-phase. @param FvDevice A pointer to the FvDevice. **/ VOID FwVolInheritAuthenticationStatus ( IN FV_DEVICE *FvDevice ) { EFI_STATUS Status; EFI_FIRMWARE_VOLUME_HEADER *CachedFvHeader; EFI_FIRMWARE_VOLUME_EXT_HEADER *CachedFvExtHeader; EFI_FIRMWARE_VOLUME2_PROTOCOL *ParentFvProtocol; UINTN Key; EFI_GUID FileNameGuid; EFI_FV_FILETYPE FileType; EFI_FV_FILE_ATTRIBUTES FileAttributes; UINTN FileSize; EFI_SECTION_TYPE SectionType; UINT32 AuthenticationStatus; EFI_FIRMWARE_VOLUME_HEADER *FvHeader; EFI_FIRMWARE_VOLUME_EXT_HEADER *FvExtHeader; UINTN BufferSize; EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb; EFI_FVB_ATTRIBUTES_2 FvbAttributes; EFI_PHYSICAL_ADDRESS BaseAddress; EFI_PEI_HOB_POINTERS Fv3Hob; if (FvDevice->Fv.ParentHandle != NULL) { CachedFvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) FvDevice->CachedFv; // // By Parent Handle, find out the FV image file and section(in another firmware volume) where the firmware volume came from // Status = gBS->HandleProtocol (FvDevice->Fv.ParentHandle, &gEfiFirmwareVolume2ProtocolGuid, (VOID **) &ParentFvProtocol); if (!EFI_ERROR (Status) && (ParentFvProtocol != NULL)) { Key = 0; do { FileType = EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE; Status = ParentFvProtocol->GetNextFile ( ParentFvProtocol, &Key, &FileType, &FileNameGuid, &FileAttributes, &FileSize ); if (EFI_ERROR (Status)) { return; } SectionType = EFI_SECTION_FIRMWARE_VOLUME_IMAGE; FvHeader = NULL; BufferSize = 0; Status = ParentFvProtocol->ReadSection ( ParentFvProtocol, &FileNameGuid, SectionType, 0, (VOID **) &FvHeader, &BufferSize, &AuthenticationStatus ); if (!EFI_ERROR (Status)) { if ((FvHeader->FvLength == CachedFvHeader->FvLength) && (FvHeader->ExtHeaderOffset == CachedFvHeader->ExtHeaderOffset)) { if (FvHeader->ExtHeaderOffset != 0) { // // Both FVs contain extension header, then compare their FV Name GUID // FvExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *) ((UINTN) FvHeader + FvHeader->ExtHeaderOffset); CachedFvExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *) ((UINTN) CachedFvHeader + CachedFvHeader->ExtHeaderOffset); if (CompareGuid (&FvExtHeader->FvName, &CachedFvExtHeader->FvName)) { // // Found the FV image section where the firmware volume came from, // and then inherit authentication status from it. // FvDevice->AuthenticationStatus = AuthenticationStatus; FreePool ((VOID *) FvHeader); return; } } else { // // Both FVs don't contain extension header, then compare their whole FV Image. // if (CompareMem ((VOID *) FvHeader, (VOID *) CachedFvHeader, (UINTN) FvHeader->FvLength) == 0) { // // Found the FV image section where the firmware volume came from // and then inherit authentication status from it. // FvDevice->AuthenticationStatus = AuthenticationStatus; FreePool ((VOID *) FvHeader); return; } } } FreePool ((VOID *) FvHeader); } } while (TRUE); } } else { Fvb = FvDevice->Fvb; Status = Fvb->GetAttributes (Fvb, &FvbAttributes); if (EFI_ERROR (Status)) { return; } if ((FvbAttributes & EFI_FVB2_MEMORY_MAPPED) != 0) { // // Get volume base address // Status = Fvb->GetPhysicalAddress (Fvb, &BaseAddress); if (EFI_ERROR (Status)) { return; } // // Get the authentication status propagated from PEI-phase to DXE. // Fv3Hob.Raw = GetHobList (); while ((Fv3Hob.Raw = GetNextHob (EFI_HOB_TYPE_FV3, Fv3Hob.Raw)) != NULL) { if (Fv3Hob.FirmwareVolume3->BaseAddress == BaseAddress) { FvDevice->AuthenticationStatus = Fv3Hob.FirmwareVolume3->AuthenticationStatus; return; } Fv3Hob.Raw = GET_NEXT_HOB (Fv3Hob); } } } }
/** Return the Virtual Memory Map of your platform This Virtual Memory Map is used by MemoryInitPei Module to initialize the MMU on your platform. @param[out] VirtualMemoryMap Array of ARM_MEMORY_REGION_DESCRIPTOR describing a Physical-to- Virtual Memory mapping. This array must be ended by a zero-filled entry **/ VOID ArmPlatformGetVirtualMemoryMap ( IN ARM_MEMORY_REGION_DESCRIPTOR** VirtualMemoryMap ) { ARM_MEMORY_REGION_ATTRIBUTES CacheAttributes; //EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttributes; UINTN Index; ARM_MEMORY_REGION_DESCRIPTOR *VirtualMemoryTable; //UINT32 SysId; //BOOLEAN HasSparseMemory; //EFI_VIRTUAL_ADDRESS SparseMemoryBase; //UINT64 SparseMemorySize; EFI_PEI_HOB_POINTERS NextHob; ASSERT (VirtualMemoryMap != NULL); VirtualMemoryTable = (ARM_MEMORY_REGION_DESCRIPTOR*)AllocatePages(EFI_SIZE_TO_PAGES (sizeof(ARM_MEMORY_REGION_DESCRIPTOR) * MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS)); if (VirtualMemoryTable == NULL) { return; } if (FeaturePcdGet(PcdCacheEnable) == TRUE) { CacheAttributes = DDR_ATTRIBUTES_CACHED; } else { CacheAttributes = DDR_ATTRIBUTES_UNCACHED; } /* // ReMap (Either NOR Flash or DRAM) VirtualMemoryTable[Index].PhysicalBase = ARM_VE_REMAP_BASE; VirtualMemoryTable[Index].VirtualBase = ARM_VE_REMAP_BASE; VirtualMemoryTable[Index].Length = ARM_VE_REMAP_SZ; if (FeaturePcdGet(PcdNorFlashRemapping) == FALSE) { // Map the NOR Flash as Secure Memory if (FeaturePcdGet(PcdCacheEnable) == TRUE) { VirtualMemoryTable[Index].Attributes = DDR_ATTRIBUTES_CACHED; } else { VirtualMemoryTable[Index].Attributes = DDR_ATTRIBUTES_UNCACHED; } } else { // DRAM mapping VirtualMemoryTable[Index].Attributes = CacheAttributes; } */ Index = OemSetVirtualMapDesc(VirtualMemoryTable, CacheAttributes); // Search for System Memory Hob that contains the EFI resource system memory s00296804 NextHob.Raw = GetHobList (); while ((NextHob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, NextHob.Raw)) != NULL) { if (NextHob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) { if (NextHob.ResourceDescriptor->PhysicalStart > BASE_4GB)//只修改4G以上的属性 { VirtualMemoryTable[++Index].PhysicalBase = NextHob.ResourceDescriptor->PhysicalStart; VirtualMemoryTable[Index].VirtualBase = NextHob.ResourceDescriptor->PhysicalStart; VirtualMemoryTable[Index].Length =NextHob.ResourceDescriptor->ResourceLength; VirtualMemoryTable[Index].Attributes = CacheAttributes; } } NextHob.Raw = GET_NEXT_HOB (NextHob); } // End of Table VirtualMemoryTable[++Index].PhysicalBase = 0; VirtualMemoryTable[Index].VirtualBase = 0; VirtualMemoryTable[Index].Length = 0; VirtualMemoryTable[Index].Attributes = (ARM_MEMORY_REGION_ATTRIBUTES)0; ASSERT((Index + 1) <= MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS); DEBUG((EFI_D_ERROR, "[%a]:[%dL] discriptor count=%d\n", __FUNCTION__, __LINE__, Index+1)); *VirtualMemoryMap = VirtualMemoryTable; }
EFI_STATUS EFIAPI InitAcpiSmmPlatform ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) /*++ Routine Description: Initializes the SMM S3 Handler Driver. Arguments: ImageHandle - The image handle of Sleep State Wake driver. SystemTable - The starndard EFI system table. Returns: EFI_OUT_OF_RESOURCES - Insufficient resources to complete function. EFI_SUCCESS - Function has completed successfully. Other - Error occured during execution. --*/ { EFI_STATUS Status; EFI_GLOBAL_NVS_AREA_PROTOCOL *AcpiNvsProtocol = NULL; UINTN MemoryLength; EFI_PEI_HOB_POINTERS Hob; Status = gBS->LocateProtocol ( &gEfiGlobalNvsAreaProtocolGuid, NULL, (VOID **) &AcpiNvsProtocol ); ASSERT_EFI_ERROR (Status); mAcpiSmm.BootScriptSaved = 0; mPlatformType = (EFI_PLATFORM_TYPE)PcdGet16 (PcdPlatformType); // // Calculate the system memory length by memory hobs // MemoryLength = 0x100000; Hob.Raw = GetFirstHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR); ASSERT (Hob.Raw != NULL); while ((Hob.Raw != NULL) && (!END_OF_HOB_LIST (Hob))) { if (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) { // // Skip the memory region below 1MB // if (Hob.ResourceDescriptor->PhysicalStart >= 0x100000) { MemoryLength += (UINTN)Hob.ResourceDescriptor->ResourceLength; } } Hob.Raw = GET_NEXT_HOB (Hob); Hob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, Hob.Raw); } ReservedS3Memory(MemoryLength); // // Locate and Register to Parent driver // Status = RegisterToDispatchDriver (); ASSERT_EFI_ERROR (Status); return EFI_SUCCESS; }