Levi Yun | 2105831 | 2024-09-23 08:18:14 +0100 | [diff] [blame^] | 1 | /** @file |
| 2 | HOB Library implementation for Standalone MM Core. |
| 3 | |
| 4 | Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR> |
| 5 | Copyright (c) 2017 - 2018, ARM Limited. All rights reserved.<BR> |
| 6 | |
| 7 | SPDX-License-Identifier: BSD-2-Clause-Patent |
| 8 | |
| 9 | **/ |
| 10 | |
| 11 | #include <Guid/MemoryAllocationHob.h> |
| 12 | |
| 13 | #include <Library/BaseMemoryLib.h> |
| 14 | #include <Library/DebugLib.h> |
| 15 | #include <Library/HobLib.h> |
| 16 | |
| 17 | #include <PiMm.h> |
| 18 | |
| 19 | // |
| 20 | // Cache copy of HobList pointer. |
| 21 | // |
| 22 | VOID *gHobList = NULL; |
| 23 | |
| 24 | VOID * |
| 25 | CreateHob ( |
| 26 | IN UINT16 HobType, |
| 27 | IN UINT16 HobLength |
| 28 | ) |
| 29 | { |
| 30 | EFI_HOB_HANDOFF_INFO_TABLE *HandOffHob; |
| 31 | EFI_HOB_GENERIC_HEADER *HobEnd; |
| 32 | EFI_PHYSICAL_ADDRESS FreeMemory; |
| 33 | VOID *Hob; |
| 34 | |
| 35 | HandOffHob = GetHobList (); |
| 36 | |
| 37 | // |
| 38 | // Check Length to avoid data overflow. |
| 39 | // |
| 40 | if (HobLength > MAX_UINT16 - 0x7) { |
| 41 | return NULL; |
| 42 | } |
| 43 | |
| 44 | HobLength = (UINT16)((HobLength + 0x7) & (~0x7)); |
| 45 | |
| 46 | FreeMemory = HandOffHob->EfiFreeMemoryTop - HandOffHob->EfiFreeMemoryBottom; |
| 47 | |
| 48 | if (FreeMemory < HobLength) { |
| 49 | return NULL; |
| 50 | } |
| 51 | |
| 52 | Hob = (VOID *)(UINTN)HandOffHob->EfiEndOfHobList; |
| 53 | ((EFI_HOB_GENERIC_HEADER *)Hob)->HobType = HobType; |
| 54 | ((EFI_HOB_GENERIC_HEADER *)Hob)->HobLength = HobLength; |
| 55 | ((EFI_HOB_GENERIC_HEADER *)Hob)->Reserved = 0; |
| 56 | |
| 57 | HobEnd = (EFI_HOB_GENERIC_HEADER *)((UINTN)Hob + HobLength); |
| 58 | HandOffHob->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS)(UINTN)HobEnd; |
| 59 | |
| 60 | HobEnd->HobType = EFI_HOB_TYPE_END_OF_HOB_LIST; |
| 61 | HobEnd->HobLength = sizeof (EFI_HOB_GENERIC_HEADER); |
| 62 | HobEnd->Reserved = 0; |
| 63 | HobEnd++; |
| 64 | HandOffHob->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS)(UINTN)HobEnd; |
| 65 | |
| 66 | return Hob; |
| 67 | } |
| 68 | |
| 69 | /** |
| 70 | Builds a HOB for a loaded PE32 module. |
| 71 | |
| 72 | This function builds a HOB for a loaded PE32 module. |
| 73 | If ModuleName is NULL, then ASSERT(). |
| 74 | If there is no additional space for HOB creation, then ASSERT(). |
| 75 | |
| 76 | @param ModuleName The GUID File Name of the module. |
| 77 | @param MemoryAllocationModule The 64 bit physical address of the module. |
| 78 | @param ModuleLength The length of the module in bytes. |
| 79 | @param EntryPoint The 64 bit physical address of the module entry point. |
| 80 | |
| 81 | **/ |
| 82 | VOID |
| 83 | EFIAPI |
| 84 | BuildModuleHob ( |
| 85 | IN CONST EFI_GUID *ModuleName, |
| 86 | IN EFI_PHYSICAL_ADDRESS MemoryAllocationModule, |
| 87 | IN UINT64 ModuleLength, |
| 88 | IN EFI_PHYSICAL_ADDRESS EntryPoint |
| 89 | ) |
| 90 | { |
| 91 | EFI_HOB_MEMORY_ALLOCATION_MODULE *Hob; |
| 92 | |
| 93 | ASSERT ( |
| 94 | ((MemoryAllocationModule & (EFI_PAGE_SIZE - 1)) == 0) && |
| 95 | ((ModuleLength & (EFI_PAGE_SIZE - 1)) == 0) |
| 96 | ); |
| 97 | |
| 98 | Hob = CreateHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, sizeof (EFI_HOB_MEMORY_ALLOCATION_MODULE)); |
| 99 | ASSERT (Hob != NULL); |
| 100 | if (Hob == NULL) { |
| 101 | return; |
| 102 | } |
| 103 | |
| 104 | CopyGuid (&(Hob->MemoryAllocationHeader.Name), &gEfiHobMemoryAllocModuleGuid); |
| 105 | Hob->MemoryAllocationHeader.MemoryBaseAddress = MemoryAllocationModule; |
| 106 | Hob->MemoryAllocationHeader.MemoryLength = ModuleLength; |
| 107 | Hob->MemoryAllocationHeader.MemoryType = EfiBootServicesCode; |
| 108 | |
| 109 | // |
| 110 | // Zero the reserved space to match HOB spec |
| 111 | // |
| 112 | ZeroMem (Hob->MemoryAllocationHeader.Reserved, sizeof (Hob->MemoryAllocationHeader.Reserved)); |
| 113 | |
| 114 | CopyGuid (&Hob->ModuleName, ModuleName); |
| 115 | Hob->EntryPoint = EntryPoint; |
| 116 | } |
| 117 | |
| 118 | /** |
| 119 | Builds a HOB that describes a chunk of system memory. |
| 120 | |
| 121 | This function builds a HOB that describes a chunk of system memory. |
| 122 | If there is no additional space for HOB creation, then ASSERT(). |
| 123 | |
| 124 | @param ResourceType The type of resource described by this HOB. |
| 125 | @param ResourceAttribute The resource attributes of the memory described by this HOB. |
| 126 | @param PhysicalStart The 64 bit physical address of memory described by this HOB. |
| 127 | @param NumberOfBytes The length of the memory described by this HOB in bytes. |
| 128 | |
| 129 | **/ |
| 130 | VOID |
| 131 | EFIAPI |
| 132 | BuildResourceDescriptorHob ( |
| 133 | IN EFI_RESOURCE_TYPE ResourceType, |
| 134 | IN EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute, |
| 135 | IN EFI_PHYSICAL_ADDRESS PhysicalStart, |
| 136 | IN UINT64 NumberOfBytes |
| 137 | ) |
| 138 | { |
| 139 | EFI_HOB_RESOURCE_DESCRIPTOR *Hob; |
| 140 | |
| 141 | Hob = CreateHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, sizeof (EFI_HOB_RESOURCE_DESCRIPTOR)); |
| 142 | ASSERT (Hob != NULL); |
| 143 | if (Hob == NULL) { |
| 144 | return; |
| 145 | } |
| 146 | |
| 147 | Hob->ResourceType = ResourceType; |
| 148 | Hob->ResourceAttribute = ResourceAttribute; |
| 149 | Hob->PhysicalStart = PhysicalStart; |
| 150 | Hob->ResourceLength = NumberOfBytes; |
| 151 | } |
| 152 | |
| 153 | /** |
| 154 | Builds a GUID HOB with a certain data length. |
| 155 | |
| 156 | This function builds a customized HOB tagged with a GUID for identification |
| 157 | and returns the start address of GUID HOB data so that caller can fill the customized data. |
| 158 | The HOB Header and Name field is already stripped. |
| 159 | If Guid is NULL, then ASSERT(). |
| 160 | If there is no additional space for HOB creation, then ASSERT(). |
| 161 | If DataLength >= (0x10000 - sizeof (EFI_HOB_GUID_TYPE)), then ASSERT(). |
| 162 | |
| 163 | @param Guid The GUID to tag the customized HOB. |
| 164 | @param DataLength The size of the data payload for the GUID HOB. |
| 165 | |
| 166 | @return The start address of GUID HOB data. |
| 167 | |
| 168 | **/ |
| 169 | VOID * |
| 170 | EFIAPI |
| 171 | BuildGuidHob ( |
| 172 | IN CONST EFI_GUID *Guid, |
| 173 | IN UINTN DataLength |
| 174 | ) |
| 175 | { |
| 176 | EFI_HOB_GUID_TYPE *Hob; |
| 177 | |
| 178 | // |
| 179 | // Make sure that data length is not too long. |
| 180 | // |
| 181 | ASSERT (DataLength <= (0xffff - sizeof (EFI_HOB_GUID_TYPE))); |
| 182 | |
| 183 | Hob = CreateHob (EFI_HOB_TYPE_GUID_EXTENSION, (UINT16)(sizeof (EFI_HOB_GUID_TYPE) + DataLength)); |
| 184 | ASSERT (Hob != NULL); |
| 185 | if (Hob == NULL) { |
| 186 | return NULL; |
| 187 | } |
| 188 | |
| 189 | CopyGuid (&Hob->Name, Guid); |
| 190 | return Hob + 1; |
| 191 | } |
| 192 | |
| 193 | /** |
| 194 | Copies a data buffer to a newly-built HOB. |
| 195 | |
| 196 | This function builds a customized HOB tagged with a GUID for identification, |
| 197 | copies the input data to the HOB data field and returns the start address of the GUID HOB data. |
| 198 | The HOB Header and Name field is already stripped. |
| 199 | If Guid is NULL, then ASSERT(). |
| 200 | If Data is NULL and DataLength > 0, then ASSERT(). |
| 201 | If there is no additional space for HOB creation, then ASSERT(). |
| 202 | If DataLength >= (0x10000 - sizeof (EFI_HOB_GUID_TYPE)), then ASSERT(). |
| 203 | |
| 204 | @param Guid The GUID to tag the customized HOB. |
| 205 | @param Data The data to be copied into the data field of the GUID HOB. |
| 206 | @param DataLength The size of the data payload for the GUID HOB. |
| 207 | |
| 208 | @return The start address of GUID HOB data. |
| 209 | |
| 210 | **/ |
| 211 | VOID * |
| 212 | EFIAPI |
| 213 | BuildGuidDataHob ( |
| 214 | IN CONST EFI_GUID *Guid, |
| 215 | IN VOID *Data, |
| 216 | IN UINTN DataLength |
| 217 | ) |
| 218 | { |
| 219 | VOID *HobData; |
| 220 | |
| 221 | ASSERT (Data != NULL || DataLength == 0); |
| 222 | |
| 223 | HobData = BuildGuidHob (Guid, DataLength); |
| 224 | |
| 225 | return CopyMem (HobData, Data, DataLength); |
| 226 | } |
| 227 | |
| 228 | /** |
| 229 | Builds a Firmware Volume HOB. |
| 230 | |
| 231 | This function builds a Firmware Volume HOB. |
| 232 | If there is no additional space for HOB creation, then ASSERT(). |
| 233 | |
| 234 | @param BaseAddress The base address of the Firmware Volume. |
| 235 | @param Length The size of the Firmware Volume in bytes. |
| 236 | |
| 237 | **/ |
| 238 | VOID |
| 239 | EFIAPI |
| 240 | BuildFvHob ( |
| 241 | IN EFI_PHYSICAL_ADDRESS BaseAddress, |
| 242 | IN UINT64 Length |
| 243 | ) |
| 244 | { |
| 245 | EFI_HOB_FIRMWARE_VOLUME *Hob; |
| 246 | |
| 247 | Hob = CreateHob (EFI_HOB_TYPE_FV, sizeof (EFI_HOB_FIRMWARE_VOLUME)); |
| 248 | ASSERT (Hob != NULL); |
| 249 | if (Hob == NULL) { |
| 250 | return; |
| 251 | } |
| 252 | |
| 253 | Hob->BaseAddress = BaseAddress; |
| 254 | Hob->Length = Length; |
| 255 | } |
| 256 | |
| 257 | /** |
| 258 | Builds a EFI_HOB_TYPE_FV2 HOB. |
| 259 | |
| 260 | This function builds a EFI_HOB_TYPE_FV2 HOB. |
| 261 | If there is no additional space for HOB creation, then ASSERT(). |
| 262 | |
| 263 | @param BaseAddress The base address of the Firmware Volume. |
| 264 | @param Length The size of the Firmware Volume in bytes. |
| 265 | @param FvName The name of the Firmware Volume. |
| 266 | @param FileName The name of the file. |
| 267 | |
| 268 | **/ |
| 269 | VOID |
| 270 | EFIAPI |
| 271 | BuildFv2Hob ( |
| 272 | IN EFI_PHYSICAL_ADDRESS BaseAddress, |
| 273 | IN UINT64 Length, |
| 274 | IN CONST EFI_GUID *FvName, |
| 275 | IN CONST EFI_GUID *FileName |
| 276 | ) |
| 277 | { |
| 278 | EFI_HOB_FIRMWARE_VOLUME2 *Hob; |
| 279 | |
| 280 | Hob = CreateHob (EFI_HOB_TYPE_FV2, sizeof (EFI_HOB_FIRMWARE_VOLUME2)); |
| 281 | ASSERT (Hob != NULL); |
| 282 | if (Hob == NULL) { |
| 283 | return; |
| 284 | } |
| 285 | |
| 286 | Hob->BaseAddress = BaseAddress; |
| 287 | Hob->Length = Length; |
| 288 | CopyGuid (&Hob->FvName, FvName); |
| 289 | CopyGuid (&Hob->FileName, FileName); |
| 290 | } |
| 291 | |
| 292 | /** |
| 293 | Builds a HOB for the CPU. |
| 294 | |
| 295 | This function builds a HOB for the CPU. |
| 296 | If there is no additional space for HOB creation, then ASSERT(). |
| 297 | |
| 298 | @param SizeOfMemorySpace The maximum physical memory addressability of the processor. |
| 299 | @param SizeOfIoSpace The maximum physical I/O addressability of the processor. |
| 300 | |
| 301 | **/ |
| 302 | VOID |
| 303 | EFIAPI |
| 304 | BuildCpuHob ( |
| 305 | IN UINT8 SizeOfMemorySpace, |
| 306 | IN UINT8 SizeOfIoSpace |
| 307 | ) |
| 308 | { |
| 309 | EFI_HOB_CPU *Hob; |
| 310 | |
| 311 | Hob = CreateHob (EFI_HOB_TYPE_CPU, sizeof (EFI_HOB_CPU)); |
| 312 | ASSERT (Hob != NULL); |
| 313 | if (Hob == NULL) { |
| 314 | return; |
| 315 | } |
| 316 | |
| 317 | Hob->SizeOfMemorySpace = SizeOfMemorySpace; |
| 318 | Hob->SizeOfIoSpace = SizeOfIoSpace; |
| 319 | |
| 320 | // |
| 321 | // Zero the reserved space to match HOB spec |
| 322 | // |
| 323 | ZeroMem (Hob->Reserved, sizeof (Hob->Reserved)); |
| 324 | } |
| 325 | |
| 326 | /** |
| 327 | Builds a HOB for the memory allocation. |
| 328 | |
| 329 | This function builds a HOB for the memory allocation. |
| 330 | If there is no additional space for HOB creation, then ASSERT(). |
| 331 | |
| 332 | @param BaseAddress The 64 bit physical address of the memory. |
| 333 | @param Length The length of the memory allocation in bytes. |
| 334 | @param MemoryType Type of memory allocated by this HOB. |
| 335 | |
| 336 | **/ |
| 337 | VOID |
| 338 | EFIAPI |
| 339 | BuildMemoryAllocationHob ( |
| 340 | IN EFI_PHYSICAL_ADDRESS BaseAddress, |
| 341 | IN UINT64 Length, |
| 342 | IN EFI_MEMORY_TYPE MemoryType |
| 343 | ) |
| 344 | { |
| 345 | EFI_HOB_MEMORY_ALLOCATION *Hob; |
| 346 | |
| 347 | ASSERT ( |
| 348 | ((BaseAddress & (EFI_PAGE_SIZE - 1)) == 0) && |
| 349 | ((Length & (EFI_PAGE_SIZE - 1)) == 0) |
| 350 | ); |
| 351 | |
| 352 | Hob = CreateHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, sizeof (EFI_HOB_MEMORY_ALLOCATION)); |
| 353 | ASSERT (Hob != NULL); |
| 354 | if (Hob == NULL) { |
| 355 | return; |
| 356 | } |
| 357 | |
| 358 | ZeroMem (&(Hob->AllocDescriptor.Name), sizeof (EFI_GUID)); |
| 359 | Hob->AllocDescriptor.MemoryBaseAddress = BaseAddress; |
| 360 | Hob->AllocDescriptor.MemoryLength = Length; |
| 361 | Hob->AllocDescriptor.MemoryType = MemoryType; |
| 362 | // |
| 363 | // Zero the reserved space to match HOB spec |
| 364 | // |
| 365 | ZeroMem (Hob->AllocDescriptor.Reserved, sizeof (Hob->AllocDescriptor.Reserved)); |
| 366 | } |
| 367 | |