hobgeneration.c

来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 526 行 · 第 1/2 页

C
526
字号
    0
  },
  { // Pointer to FlushInstructionCache
    EFI_HOB_TYPE_GUID_EXTENSION,       // Hob type
    sizeof (PROTOCOL_HOB),             // Hob size
    0,                                 // reserved
    EFI_PEI_FLUSH_INSTRUCTION_CACHE_GUID,
    NULL
  },
  { // Pointer to TransferControl
    EFI_HOB_TYPE_GUID_EXTENSION,       // Hob type
    sizeof (PROTOCOL_HOB),             // Hob size
    0,                                 // reserved
    EFI_PEI_TRANSFER_CONTROL_GUID,
    NULL
  },
  { // Pointer to PeCoffLoader
    EFI_HOB_TYPE_GUID_EXTENSION,       // Hob type
    sizeof (PROTOCOL_HOB),             // Hob size
    0,                                 // reserved
    EFI_PEI_PE_COFF_LOADER_GUID,
    NULL
  },
  { // Pointer to EfiDecompress
    EFI_HOB_TYPE_GUID_EXTENSION,       // Hob type
    sizeof (PROTOCOL_HOB),             // Hob size
    0,                                 // reserved
    EFI_DECOMPRESS_PROTOCOL_GUID,
    NULL
  },
  { // Pointer to TianoDecompress
    EFI_HOB_TYPE_GUID_EXTENSION,       // Hob type
    sizeof (PROTOCOL_HOB),             // Hob size
    0,                                 // reserved
    EFI_TIANO_DECOMPRESS_PROTOCOL_GUID,
    NULL
  },
  { // Pointer to ReportStatusCode
    EFI_HOB_TYPE_GUID_EXTENSION,       // Hob type
    sizeof (PROTOCOL_HOB),             // Hob size
    0,                                 // reserved
    EFI_STATUS_CODE_RUNTIME_PROTOCOL_GUID,
    NULL
  },
  { // EFILDR Memory Descriptor
    EFI_HOB_TYPE_GUID_EXTENSION,       // Hob type
    sizeof (MEMORY_DESC_HOB),          // Hob size
    0,                                 // reserved
    EFI_LDR_MEMORY_DESCRIPTOR_GUID,
    0,
    NULL
  },
  { // Pci Express Base Address Hob
    EFI_HOB_TYPE_GUID_EXTENSION,       // Hob type
    sizeof (PCI_EXPRESS_BASE_HOB),     // Hob size
    0,                                 // reserved
    EFI_PCI_EXPRESS_BASE_ADDRESS_GUID,
    {
      0,
      0,
      0,
    }
  },
  { // Acpi Description Hob
    EFI_HOB_TYPE_GUID_EXTENSION,       // Hob type
    sizeof (ACPI_DESCRIPTION_HOB),     // Hob size
    0,                                 // reserved
    EFI_ACPI_DESCRIPTION_GUID,
    {
      0,
    }
  },
  { // EndOfHobList
    EFI_HOB_TYPE_END_OF_HOB_LIST,      // HobType
    sizeof (EFI_HOB_GENERIC_HEADER),   // HobLength
    0                                  // Reserved
  }
};

HOB_TEMPLATE  *gHob = &gHobTemplate;

VOID *
PrepareHobMemory (
  IN UINTN                    NumberOfMemoryMapEntries,
  IN EFI_MEMORY_DESCRIPTOR    *EfiMemoryDescriptor
  )
{
  UINTN                Index;
  EFI_PHYSICAL_ADDRESS PhysicalEnd;

  //
  // Prepare Low Memory
  // 0x18 pages is 72 KB.
  //
  gHob->MemoryFreeUnder1MB.ResourceLength = EFI_MEMORY_BELOW_1MB_END - EFI_MEMORY_BELOW_1MB_START;
  gHob->MemoryFreeUnder1MB.PhysicalStart  = EFI_MEMORY_BELOW_1MB_START;

  //
  // Prepare High Memory
  // Assume Memory Map is ordered from low to high
  //
  gHob->MemoryAbove1MB.PhysicalStart   = 0;
  gHob->MemoryAbove1MB.ResourceLength  = 0;
  gHob->MemoryAbove4GB.PhysicalStart   = 0;
  gHob->MemoryAbove4GB.ResourceLength  = 0;

  PhysicalEnd = 0;
  for (Index = 0; Index < NumberOfMemoryMapEntries; Index++) {
    //
    // Skip regions below 1MB
    //
    if (EfiMemoryDescriptor[Index].PhysicalStart < 0x100000) {
      continue;
    }
    //
    // Process regions above 1MB
    //
    if (EfiMemoryDescriptor[Index].PhysicalStart >= 0x100000) {
      if (EfiMemoryDescriptor[Index].Type == EfiConventionalMemory) {
        if (gHob->MemoryAbove1MB.PhysicalStart == 0) {
          gHob->MemoryAbove1MB.PhysicalStart = EfiMemoryDescriptor[Index].PhysicalStart;
          gHob->MemoryAbove1MB.ResourceLength = LShiftU64 (EfiMemoryDescriptor[Index].NumberOfPages, EFI_PAGE_SHIFT);
        } else if (PhysicalEnd == EfiMemoryDescriptor[Index].PhysicalStart) {
          gHob->MemoryAbove1MB.ResourceLength += LShiftU64 (EfiMemoryDescriptor[Index].NumberOfPages, EFI_PAGE_SHIFT);
        }
        PhysicalEnd = EfiMemoryDescriptor[Index].PhysicalStart + \
                      LShiftU64 (EfiMemoryDescriptor[Index].NumberOfPages, EFI_PAGE_SHIFT);
      }
      if ((EfiMemoryDescriptor[Index].Type == EfiReservedMemoryType) ||
          (EfiMemoryDescriptor[Index].Type >= EfiACPIReclaimMemory) ) {
        continue;
      }
      if ((EfiMemoryDescriptor[Index].Type == EfiRuntimeServicesCode) ||
          (EfiMemoryDescriptor[Index].Type == EfiRuntimeServicesData)) {
        break;
      }
    }
    //
    // Process region above 4GB
    //
    if (EfiMemoryDescriptor[Index].PhysicalStart >= 0x100000000) {
      if (EfiMemoryDescriptor[Index].Type == EfiConventionalMemory) {
        if (gHob->MemoryAbove4GB.PhysicalStart == 0) {
          gHob->MemoryAbove4GB.PhysicalStart  = EfiMemoryDescriptor[Index].PhysicalStart;
          gHob->MemoryAbove4GB.ResourceLength = LShiftU64 (EfiMemoryDescriptor[Index].NumberOfPages, EFI_PAGE_SHIFT);
        }
        if (gHob->MemoryAbove4GB.PhysicalStart + gHob->MemoryAbove4GB.ResourceLength == 
            EfiMemoryDescriptor[Index].PhysicalStart) {
          gHob->MemoryAbove4GB.ResourceLength += LShiftU64 (EfiMemoryDescriptor[Index].NumberOfPages, EFI_PAGE_SHIFT);
        }
      }
    }
  }

  if (gHob->MemoryAbove4GB.ResourceLength == 0) {
    //
    // If there is no memory above 4GB then change the resource descriptor HOB
    //  into another type. I'm doing this as it's unclear if a resource
    //  descriptor HOB of length zero is valid. Spec does not say it's illegal,
    //  but code in EDK does not seem to handle this case.
    //
    gHob->MemoryAbove4GB.Header.HobType = EFI_HOB_TYPE_UNUSED;
  }

  return (VOID *)(UINTN)(gHob->MemoryAbove1MB.PhysicalStart + gHob->MemoryAbove1MB.ResourceLength);
}

VOID *
PrepareHobStack (
  IN VOID *StackTop
  )
{
  gHob->Stack.AllocDescriptor.MemoryLength      = EFI_MEMORY_STACK_PAGE_NUM * EFI_PAGE_SIZE;
  gHob->Stack.AllocDescriptor.MemoryBaseAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)StackTop - gHob->Stack.AllocDescriptor.MemoryLength;

  return (VOID *)(UINTN)gHob->Stack.AllocDescriptor.MemoryBaseAddress;
}

VOID *
PrepareHobMemoryDescriptor (
  VOID                          *MemoryDescriptorTop,
  UINTN                         MemDescCount,
  EFI_MEMORY_DESCRIPTOR         *MemDesc
  )
{
  gHob->MemoryDescriptor.MemDescCount = MemDescCount;
  gHob->MemoryDescriptor.MemDesc = (EFI_MEMORY_DESCRIPTOR *)((UINTN)MemoryDescriptorTop - MemDescCount * sizeof(EFI_MEMORY_DESCRIPTOR));

  EfiCommonLibCopyMem (gHob->MemoryDescriptor.MemDesc, MemDesc, MemDescCount * sizeof(EFI_MEMORY_DESCRIPTOR));

  return gHob->MemoryDescriptor.MemDesc;
}

VOID
PrepareHobBfv (
  VOID  *Bfv,
  UINTN BfvLength
  )
{
  UINTN BfvLengthPageSize;

  //
  // Calculate BFV location at top of the memory region.
  // This is like a RAM Disk. Align to page boundry.
  //
  BfvLengthPageSize = EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (BfvLength));
 
  gHob->Bfv.BaseAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)Bfv;
  gHob->Bfv.Length = BfvLength;

  //
  // Resource descriptor for the FV
  //
  gHob->BfvResource.PhysicalStart = gHob->Bfv.BaseAddress;
  gHob->BfvResource.ResourceLength = gHob->Bfv.Length;
}

VOID
PrepareHobDxeCore (
  VOID                  *DxeCoreEntryPoint,
  EFI_PHYSICAL_ADDRESS  DxeCoreImageBase,
  UINT64                DxeCoreLength
  )
{
  gHob->DxeCore.MemoryAllocationHeader.MemoryBaseAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)DxeCoreEntryPoint;
  gHob->DxeCore.MemoryAllocationHeader.MemoryLength = DxeCoreLength;
  gHob->DxeCore.EntryPoint = (EFI_PHYSICAL_ADDRESS)(UINTN)DxeCoreEntryPoint;
}

VOID
PrepareHobPhit (
  VOID *MemoryTop,
  VOID *FreeMemoryTop
  )
{
  gHob->Phit.EfiMemoryTop        = (EFI_PHYSICAL_ADDRESS)(UINTN)MemoryTop;
  gHob->Phit.EfiMemoryBottom     = gHob->Phit.EfiMemoryTop - CONSUMED_MEMORY;
  gHob->Phit.EfiFreeMemoryTop    = (EFI_PHYSICAL_ADDRESS)(UINTN)FreeMemoryTop;
  gHob->Phit.EfiFreeMemoryBottom = gHob->Phit.EfiMemoryBottom + sizeof(HOB_TEMPLATE);

  EfiCommonLibCopyMem ((VOID *)(UINTN)gHob->Phit.EfiMemoryBottom, gHob, sizeof(HOB_TEMPLATE));
  gHob = (HOB_TEMPLATE *)(UINTN)gHob->Phit.EfiMemoryBottom;

  gHob->Phit.EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS)(UINTN)&gHob->EndOfHobList;
}

VOID
CompleteHobGeneration (
  VOID
  )
{
  gHob->MemoryAllocation.AllocDescriptor.MemoryBaseAddress  = gHob->Phit.EfiFreeMemoryTop;
  gHob->MemoryAllocation.AllocDescriptor.MemoryLength       = gHob->Phit.EfiMemoryTop - gHob->Phit.EfiFreeMemoryTop;

  //
  // adjust Above1MB ResourceLength
  //
  if (gHob->MemoryAbove1MB.PhysicalStart + gHob->MemoryAbove1MB.ResourceLength < gHob->Phit.EfiMemoryTop) {
    gHob->MemoryAbove1MB.ResourceLength = gHob->Phit.EfiMemoryTop - gHob->MemoryAbove1MB.PhysicalStart;
  }
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?