+ Get available system memory below 1MB by specified size.\r
+\r
+ @param[in] WakeupBufferSize Wakeup buffer size required\r
+\r
+ @retval other Return wakeup buffer address below 1MB.\r
+ @retval -1 Cannot find free memory below 1MB.\r
+**/\r
+UINTN\r
+GetWakeupBuffer (\r
+ IN UINTN WakeupBufferSize\r
+ )\r
+{\r
+ EFI_PEI_HOB_POINTERS Hob;\r
+ UINTN WakeupBufferStart;\r
+ UINTN WakeupBufferEnd;\r
+\r
+ WakeupBufferSize = (WakeupBufferSize + SIZE_4KB - 1) & ~(SIZE_4KB - 1);\r
+\r
+ //\r
+ // Get the HOB list for processing\r
+ //\r
+ Hob.Raw = GetHobList ();\r
+\r
+ //\r
+ // Collect memory ranges\r
+ //\r
+ while (!END_OF_HOB_LIST (Hob)) {\r
+ if (Hob.Header->HobType == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {\r
+ if ((Hob.ResourceDescriptor->PhysicalStart < BASE_1MB) &&\r
+ (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) &&\r
+ ((Hob.ResourceDescriptor->ResourceAttribute &\r
+ (EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED |\r
+ EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED |\r
+ EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED\r
+ )) == 0)\r
+ ) {\r
+ //\r
+ // Need memory under 1MB to be collected here\r
+ //\r
+ WakeupBufferEnd = (UINTN) (Hob.ResourceDescriptor->PhysicalStart + Hob.ResourceDescriptor->ResourceLength);\r
+ if (WakeupBufferEnd > BASE_1MB) {\r
+ //\r
+ // Wakeup buffer should be under 1MB\r
+ //\r
+ WakeupBufferEnd = BASE_1MB;\r
+ }\r
+ while (WakeupBufferEnd > WakeupBufferSize) {\r
+ //\r
+ // Wakeup buffer should be aligned on 4KB\r
+ //\r
+ WakeupBufferStart = (WakeupBufferEnd - WakeupBufferSize) & ~(SIZE_4KB - 1);\r
+ if (WakeupBufferStart < Hob.ResourceDescriptor->PhysicalStart) {\r
+ break;\r
+ }\r
+ if (CheckOverlapWithAllocatedBuffer (WakeupBufferStart, WakeupBufferEnd)) {\r
+ //\r
+ // If this range is overlapped with existing allocated buffer, skip it\r
+ // and find the next range\r
+ //\r
+ WakeupBufferEnd -= WakeupBufferSize;\r
+ continue;\r
+ }\r
+ DEBUG ((DEBUG_INFO, "WakeupBufferStart = %x, WakeupBufferSize = %x\n",\r
+ WakeupBufferStart, WakeupBufferSize));\r
+ return WakeupBufferStart;\r
+ }\r
+ }\r
+ }\r
+ //\r
+ // Find the next HOB\r
+ //\r
+ Hob.Raw = GET_NEXT_HOB (Hob);\r
+ }\r
+\r
+ return (UINTN) -1;\r
+}\r
+\r