summaryrefslogtreecommitdiffstats
path: root/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/Arm/CreateHobList.c
blob: 80ed532352af9c075734cfec4655fb2784e29da3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
/** @file
  Creates HOB during Standalone MM Foundation entry point
  on ARM platforms.

Copyright (c) 2017 - 2021, Arm Ltd. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent

**/

#include <PiMm.h>

#include <PiPei.h>
#include <Guid/MmramMemoryReserve.h>
#include <Guid/MpInformation.h>

#include <StandaloneMmCpu.h>
#include <Library/Arm/StandaloneMmCoreEntryPoint.h>
#include <Library/ArmMmuLib.h>
#include <Library/ArmSvcLib.h>
#include <Library/DebugLib.h>
#include <Library/HobLib.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/SerialPortLib.h>

#include <IndustryStandard/ArmStdSmc.h>

extern EFI_HOB_HANDOFF_INFO_TABLE *
HobConstructor (
  IN VOID   *EfiMemoryBegin,
  IN UINTN  EfiMemoryLength,
  IN VOID   *EfiFreeMemoryBottom,
  IN VOID   *EfiFreeMemoryTop
  );

// GUID to identify HOB with whereabouts of communication buffer with Normal
// World
extern EFI_GUID  gEfiStandaloneMmNonSecureBufferGuid;

// GUID to identify HOB where the entry point of the CPU driver will be
// populated to allow this entry point driver to invoke it upon receipt of an
// event
extern EFI_GUID  gEfiMmCpuDriverEpDescriptorGuid;

/**
  Use the boot information passed by privileged firmware to populate a HOB list
  suitable for consumption by the MM Core and drivers.

  @param  [in, out] CpuDriverEntryPoint   Address of MM CPU driver entrypoint
  @param  [in]      PayloadBootInfo       Boot information passed by privileged
                                          firmware

**/
VOID *
CreateHobListFromBootInfo (
  IN  OUT  PI_MM_CPU_DRIVER_ENTRYPOINT     *CpuDriverEntryPoint,
  IN       EFI_SECURE_PARTITION_BOOT_INFO  *PayloadBootInfo
  )
{
  EFI_HOB_HANDOFF_INFO_TABLE      *HobStart;
  EFI_RESOURCE_ATTRIBUTE_TYPE     Attributes;
  UINT32                          Index;
  UINT32                          BufferSize;
  UINT32                          Flags;
  EFI_MMRAM_HOB_DESCRIPTOR_BLOCK  *MmramRangesHob;
  EFI_MMRAM_DESCRIPTOR            *MmramRanges;
  EFI_MMRAM_DESCRIPTOR            *NsCommBufMmramRange;
  MP_INFORMATION_HOB_DATA         *MpInformationHobData;
  EFI_PROCESSOR_INFORMATION       *ProcInfoBuffer;
  EFI_SECURE_PARTITION_CPU_INFO   *CpuInfo;
  MM_CPU_DRIVER_EP_DESCRIPTOR     *CpuDriverEntryPointDesc;

  // Create a hoblist with a PHIT and EOH
  HobStart = HobConstructor (
               (VOID *)(UINTN)PayloadBootInfo->SpMemBase,
               (UINTN)PayloadBootInfo->SpMemLimit - PayloadBootInfo->SpMemBase,
               (VOID *)(UINTN)PayloadBootInfo->SpHeapBase,
               (VOID *)(UINTN)(PayloadBootInfo->SpHeapBase + PayloadBootInfo->SpHeapSize)
               );

  // Check that the Hoblist starts at the bottom of the Heap
  ASSERT (HobStart == (VOID *)(UINTN)PayloadBootInfo->SpHeapBase);

  // Build a Boot Firmware Volume HOB
  BuildFvHob (PayloadBootInfo->SpImageBase, PayloadBootInfo->SpImageSize);

  // Build a resource descriptor Hob that describes the available physical
  // memory range
  Attributes = (
                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
                );

  BuildResourceDescriptorHob (
    EFI_RESOURCE_SYSTEM_MEMORY,
    Attributes,
    (UINTN)PayloadBootInfo->SpMemBase,
    PayloadBootInfo->SpMemLimit - PayloadBootInfo->SpMemBase
    );

  // Find the size of the GUIDed HOB with MP information
  BufferSize  = sizeof (MP_INFORMATION_HOB_DATA);
  BufferSize += sizeof (EFI_PROCESSOR_INFORMATION) * PayloadBootInfo->NumCpus;

  // Create a Guided MP information HOB to enable the ARM TF CPU driver to
  // perform per-cpu allocations.
  MpInformationHobData = BuildGuidHob (&gMpInformationHobGuid, BufferSize);

  // Populate the MP information HOB with the topology information passed by
  // privileged firmware
  MpInformationHobData->NumberOfProcessors        = PayloadBootInfo->NumCpus;
  MpInformationHobData->NumberOfEnabledProcessors = PayloadBootInfo->NumCpus;
  ProcInfoBuffer                                  = MpInformationHobData->ProcessorInfoBuffer;
  CpuInfo                                         = PayloadBootInfo->CpuInfo;

  for (Index = 0; Index < PayloadBootInfo->NumCpus; Index++) {
    ProcInfoBuffer[Index].ProcessorId      = CpuInfo[Index].Mpidr;
    ProcInfoBuffer[Index].Location.Package = GET_CLUSTER_ID (CpuInfo[Index].Mpidr);
    ProcInfoBuffer[Index].Location.Core    = GET_CORE_ID (CpuInfo[Index].Mpidr);
    ProcInfoBuffer[Index].Location.Thread  = GET_CORE_ID (CpuInfo[Index].Mpidr);

    Flags = PROCESSOR_ENABLED_BIT | PROCESSOR_HEALTH_STATUS_BIT;
    if (CpuInfo[Index].Flags & CPU_INFO_FLAG_PRIMARY_CPU) {
      Flags |= PROCESSOR_AS_BSP_BIT;
    }

    ProcInfoBuffer[Index].StatusFlag = Flags;
  }

  // Create a Guided HOB to tell the ARM TF CPU driver the location and length
  // of the communication buffer shared with the Normal world.
  NsCommBufMmramRange = (EFI_MMRAM_DESCRIPTOR *)BuildGuidHob (
                                                  &gEfiStandaloneMmNonSecureBufferGuid,
                                                  sizeof (EFI_MMRAM_DESCRIPTOR)
                                                  );
  NsCommBufMmramRange->PhysicalStart = PayloadBootInfo->SpNsCommBufBase;
  NsCommBufMmramRange->CpuStart      = PayloadBootInfo->SpNsCommBufBase;
  NsCommBufMmramRange->PhysicalSize  = PayloadBootInfo->SpNsCommBufSize;
  NsCommBufMmramRange->RegionState   = EFI_CACHEABLE | EFI_ALLOCATED;

  // Create a Guided HOB to enable the ARM TF CPU driver to share its entry
  // point and populate it with the address of the shared buffer
  CpuDriverEntryPointDesc = (MM_CPU_DRIVER_EP_DESCRIPTOR *)BuildGuidHob (
                                                             &gEfiMmCpuDriverEpDescriptorGuid,
                                                             sizeof (MM_CPU_DRIVER_EP_DESCRIPTOR)
                                                             );

  *CpuDriverEntryPoint                      = NULL;
  CpuDriverEntryPointDesc->MmCpuDriverEpPtr = CpuDriverEntryPoint;

  // Find the size of the GUIDed HOB with SRAM ranges
  BufferSize  = sizeof (EFI_MMRAM_HOB_DESCRIPTOR_BLOCK);
  BufferSize += PayloadBootInfo->NumSpMemRegions * sizeof (EFI_MMRAM_DESCRIPTOR);

  // Create a GUIDed HOB with SRAM ranges
  MmramRangesHob = BuildGuidHob (&gEfiMmPeiMmramMemoryReserveGuid, BufferSize);

  // Fill up the number of MMRAM memory regions
  MmramRangesHob->NumberOfMmReservedRegions = PayloadBootInfo->NumSpMemRegions;
  // Fill up the MMRAM ranges
  MmramRanges = &MmramRangesHob->Descriptor[0];

  // Base and size of memory occupied by the Standalone MM image
  MmramRanges[0].PhysicalStart = PayloadBootInfo->SpImageBase;
  MmramRanges[0].CpuStart      = PayloadBootInfo->SpImageBase;
  MmramRanges[0].PhysicalSize  = PayloadBootInfo->SpImageSize;
  MmramRanges[0].RegionState   = EFI_CACHEABLE | EFI_ALLOCATED;

  // Base and size of buffer shared with privileged Secure world software
  MmramRanges[1].PhysicalStart = PayloadBootInfo->SpSharedBufBase;
  MmramRanges[1].CpuStart      = PayloadBootInfo->SpSharedBufBase;
  MmramRanges[1].PhysicalSize  = PayloadBootInfo->SpSharedBufSize;
  MmramRanges[1].RegionState   = EFI_CACHEABLE | EFI_ALLOCATED;

  // Base and size of buffer used for synchronous communication with Normal
  // world software
  MmramRanges[2].PhysicalStart = PayloadBootInfo->SpNsCommBufBase;
  MmramRanges[2].CpuStart      = PayloadBootInfo->SpNsCommBufBase;
  MmramRanges[2].PhysicalSize  = PayloadBootInfo->SpNsCommBufSize;
  MmramRanges[2].RegionState   = EFI_CACHEABLE | EFI_ALLOCATED;

  // Base and size of memory allocated for stacks for all cpus
  MmramRanges[3].PhysicalStart = PayloadBootInfo->SpStackBase;
  MmramRanges[3].CpuStart      = PayloadBootInfo->SpStackBase;
  MmramRanges[3].PhysicalSize  = PayloadBootInfo->SpPcpuStackSize * PayloadBootInfo->NumCpus;
  MmramRanges[3].RegionState   = EFI_CACHEABLE | EFI_ALLOCATED;

  // Base and size of heap memory shared by all cpus
  MmramRanges[4].PhysicalStart = (EFI_PHYSICAL_ADDRESS)(UINTN)HobStart;
  MmramRanges[4].CpuStart      = (EFI_PHYSICAL_ADDRESS)(UINTN)HobStart;
  MmramRanges[4].PhysicalSize  = HobStart->EfiFreeMemoryBottom - (EFI_PHYSICAL_ADDRESS)(UINTN)HobStart;
  MmramRanges[4].RegionState   = EFI_CACHEABLE | EFI_ALLOCATED;

  // Base and size of heap memory shared by all cpus
  MmramRanges[5].PhysicalStart = HobStart->EfiFreeMemoryBottom;
  MmramRanges[5].CpuStart      = HobStart->EfiFreeMemoryBottom;
  MmramRanges[5].PhysicalSize  = HobStart->EfiFreeMemoryTop - HobStart->EfiFreeMemoryBottom;
  MmramRanges[5].RegionState   = EFI_CACHEABLE;

  return HobStart;
}