]> git.proxmox.com Git - mirror_edk2.git/blob - ArmPkg/Library/BdsLib/BdsHelper.c
bd1fa005e83e257943d19e2c31a412508774df1d
[mirror_edk2.git] / ArmPkg / Library / BdsLib / BdsHelper.c
1 /** @file
2 *
3 * Copyright (c) 2011, ARM Limited. All rights reserved.
4 *
5 * This program and the accompanying materials
6 * are licensed and made available under the terms and conditions of the BSD License
7 * which accompanies this distribution. The full text of the license may be found at
8 * http://opensource.org/licenses/bsd-license.php
9 *
10 * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 *
13 **/
14
15 #include "BdsInternal.h"
16
17 #include <Library/DxeServicesTableLib.h>
18 #include <Library/HobLib.h>
19 #include <Library/TimerLib.h>
20 #include <Library/PrintLib.h>
21 #include <Library/SerialPortLib.h>
22
23 STATIC CHAR8 *mTokenList[] = {
24 /*"SEC",*/
25 "PEI",
26 "DXE",
27 "BDS",
28 NULL
29 };
30
31 EFI_STATUS
32 ShutdownUefiBootServices (
33 VOID
34 )
35 {
36 EFI_STATUS Status;
37 UINTN MemoryMapSize;
38 EFI_MEMORY_DESCRIPTOR *MemoryMap;
39 UINTN MapKey;
40 UINTN DescriptorSize;
41 UINT32 DescriptorVersion;
42 UINTN Pages;
43
44 MemoryMap = NULL;
45 MemoryMapSize = 0;
46 Pages = 0;
47 do {
48 Status = gBS->GetMemoryMap (
49 &MemoryMapSize,
50 MemoryMap,
51 &MapKey,
52 &DescriptorSize,
53 &DescriptorVersion
54 );
55 if (Status == EFI_BUFFER_TOO_SMALL) {
56
57 Pages = EFI_SIZE_TO_PAGES (MemoryMapSize) + 1;
58 MemoryMap = AllocatePages (Pages);
59
60 //
61 // Get System MemoryMap
62 //
63 Status = gBS->GetMemoryMap (
64 &MemoryMapSize,
65 MemoryMap,
66 &MapKey,
67 &DescriptorSize,
68 &DescriptorVersion
69 );
70 }
71
72 // Don't do anything between the GetMemoryMap() and ExitBootServices()
73 if (!EFI_ERROR(Status)) {
74 Status = gBS->ExitBootServices (gImageHandle, MapKey);
75 if (EFI_ERROR(Status)) {
76 FreePages (MemoryMap, Pages);
77 MemoryMap = NULL;
78 MemoryMapSize = 0;
79 }
80 }
81 } while (EFI_ERROR(Status));
82
83 return Status;
84 }
85
86 /**
87 Connect all DXE drivers
88
89 @retval EFI_SUCCESS All drivers have been connected
90 @retval EFI_NOT_FOUND No handles match the search.
91 @retval EFI_OUT_OF_RESOURCES There is not resource pool memory to store the matching results.
92
93 **/
94 EFI_STATUS
95 BdsConnectAllDrivers (
96 VOID
97 )
98 {
99 UINTN HandleCount, Index;
100 EFI_HANDLE *HandleBuffer;
101 EFI_STATUS Status;
102
103 do {
104 // Locate all the driver handles
105 Status = gBS->LocateHandleBuffer (
106 AllHandles,
107 NULL,
108 NULL,
109 &HandleCount,
110 &HandleBuffer
111 );
112 if (EFI_ERROR (Status)) {
113 break;
114 }
115
116 // Connect every handles
117 for (Index = 0; Index < HandleCount; Index++) {
118 gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE);
119 }
120
121 if (HandleBuffer != NULL) {
122 FreePool (HandleBuffer);
123 }
124
125 // Check if new handles have been created after the start of the previous handles
126 Status = gDS->Dispatch ();
127 } while (!EFI_ERROR(Status));
128
129 return EFI_SUCCESS;
130 }
131
132 STATIC
133 EFI_STATUS
134 InsertSystemMemoryResources (
135 LIST_ENTRY *ResourceList,
136 EFI_HOB_RESOURCE_DESCRIPTOR *ResHob
137 )
138 {
139 BDS_SYSTEM_MEMORY_RESOURCE *NewResource;
140 LIST_ENTRY *Link;
141 LIST_ENTRY *NextLink;
142 LIST_ENTRY AttachedResources;
143 BDS_SYSTEM_MEMORY_RESOURCE *Resource;
144 EFI_PHYSICAL_ADDRESS NewResourceEnd;
145
146 if (IsListEmpty (ResourceList)) {
147 NewResource = AllocateZeroPool (sizeof(BDS_SYSTEM_MEMORY_RESOURCE));
148 NewResource->PhysicalStart = ResHob->PhysicalStart;
149 NewResource->ResourceLength = ResHob->ResourceLength;
150 InsertTailList (ResourceList, &NewResource->Link);
151 return EFI_SUCCESS;
152 }
153
154 InitializeListHead (&AttachedResources);
155
156 Link = ResourceList->ForwardLink;
157 ASSERT (Link != NULL);
158 while (Link != ResourceList) {
159 Resource = (BDS_SYSTEM_MEMORY_RESOURCE*)Link;
160
161 // Sanity Check. The resources should not overlapped.
162 ASSERT(!((ResHob->PhysicalStart >= Resource->PhysicalStart) && (ResHob->PhysicalStart < (Resource->PhysicalStart + Resource->ResourceLength))));
163 ASSERT(!((ResHob->PhysicalStart + ResHob->ResourceLength - 1 >= Resource->PhysicalStart) &&
164 ((ResHob->PhysicalStart + ResHob->ResourceLength - 1) < (Resource->PhysicalStart + Resource->ResourceLength))));
165
166 // The new resource is attached after this resource descriptor
167 if (ResHob->PhysicalStart == Resource->PhysicalStart + Resource->ResourceLength) {
168 Resource->ResourceLength = Resource->ResourceLength + ResHob->ResourceLength;
169
170 NextLink = RemoveEntryList (&Resource->Link);
171 InsertTailList (&AttachedResources, &Resource->Link);
172 Link = NextLink;
173 }
174 // The new resource is attached before this resource descriptor
175 else if (ResHob->PhysicalStart + ResHob->ResourceLength == Resource->PhysicalStart) {
176 Resource->PhysicalStart = ResHob->PhysicalStart;
177 Resource->ResourceLength = Resource->ResourceLength + ResHob->ResourceLength;
178
179 NextLink = RemoveEntryList (&Resource->Link);
180 InsertTailList (&AttachedResources, &Resource->Link);
181 Link = NextLink;
182 } else {
183 Link = Link->ForwardLink;
184 }
185 }
186
187 if (!IsListEmpty (&AttachedResources)) {
188 // See if we can merge the attached resource with other resources
189
190 NewResource = (BDS_SYSTEM_MEMORY_RESOURCE*)GetFirstNode (&AttachedResources);
191 Link = RemoveEntryList (&NewResource->Link);
192 while (!IsListEmpty (&AttachedResources)) {
193 // Merge resources
194 Resource = (BDS_SYSTEM_MEMORY_RESOURCE*)Link;
195
196 // Ensure they overlap each other
197 ASSERT(
198 ((NewResource->PhysicalStart >= Resource->PhysicalStart) && (NewResource->PhysicalStart < (Resource->PhysicalStart + Resource->ResourceLength))) ||
199 (((NewResource->PhysicalStart + NewResource->ResourceLength) >= Resource->PhysicalStart) && ((NewResource->PhysicalStart + NewResource->ResourceLength) < (Resource->PhysicalStart + Resource->ResourceLength)))
200 );
201
202 NewResourceEnd = MAX (NewResource->PhysicalStart + NewResource->ResourceLength, Resource->PhysicalStart + Resource->ResourceLength);
203 NewResource->PhysicalStart = MIN (NewResource->PhysicalStart, Resource->PhysicalStart);
204 NewResource->ResourceLength = NewResourceEnd - NewResource->PhysicalStart;
205
206 Link = RemoveEntryList (Link);
207 }
208 } else {
209 // None of the Resource of the list is attached to this ResHob. Create a new entry for it
210 NewResource = AllocateZeroPool (sizeof(BDS_SYSTEM_MEMORY_RESOURCE));
211 NewResource->PhysicalStart = ResHob->PhysicalStart;
212 NewResource->ResourceLength = ResHob->ResourceLength;
213 }
214 InsertTailList (ResourceList, &NewResource->Link);
215 return EFI_SUCCESS;
216 }
217
218 EFI_STATUS
219 GetSystemMemoryResources (
220 IN LIST_ENTRY *ResourceList
221 )
222 {
223 EFI_HOB_RESOURCE_DESCRIPTOR *ResHob;
224
225 InitializeListHead (ResourceList);
226
227 // Find the first System Memory Resource Descriptor
228 ResHob = (EFI_HOB_RESOURCE_DESCRIPTOR *)GetFirstHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR);
229 while ((ResHob != NULL) && (ResHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY)) {
230 ResHob = (EFI_HOB_RESOURCE_DESCRIPTOR *)GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR,(VOID *)((UINTN)ResHob + ResHob->Header.HobLength));
231 }
232
233 // Did not find any
234 if (ResHob == NULL) {
235 return EFI_NOT_FOUND;
236 } else {
237 InsertSystemMemoryResources (ResourceList, ResHob);
238 }
239
240 ResHob = (EFI_HOB_RESOURCE_DESCRIPTOR *)GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR,(VOID *)((UINTN)ResHob + ResHob->Header.HobLength));
241 while (ResHob != NULL) {
242 if (ResHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) {
243 InsertSystemMemoryResources (ResourceList, ResHob);
244 }
245 ResHob = (EFI_HOB_RESOURCE_DESCRIPTOR *)GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR,(VOID *)((UINTN)ResHob + ResHob->Header.HobLength));
246 }
247
248 return EFI_SUCCESS;
249 }
250
251 VOID
252 PrintPerformance (
253 VOID
254 )
255 {
256 UINTN Key;
257 CONST VOID *Handle;
258 CONST CHAR8 *Token, *Module;
259 UINT64 Start, Stop, TimeStamp;
260 UINT64 Delta, TicksPerSecond, Milliseconds;
261 UINTN Index;
262 CHAR8 Buffer[100];
263 UINTN CharCount;
264 BOOLEAN CountUp;
265
266 TicksPerSecond = GetPerformanceCounterProperties (&Start, &Stop);
267 if (Start < Stop) {
268 CountUp = TRUE;
269 } else {
270 CountUp = FALSE;
271 }
272
273 TimeStamp = 0;
274 Key = 0;
275 do {
276 Key = GetPerformanceMeasurement (Key, (CONST VOID **)&Handle, &Token, &Module, &Start, &Stop);
277 if (Key != 0) {
278 for (Index = 0; mTokenList[Index] != NULL; Index++) {
279 if (AsciiStriCmp (mTokenList[Index], Token) == 0) {
280 Delta = CountUp?(Stop - Start):(Start - Stop);
281 TimeStamp += Delta;
282 Milliseconds = DivU64x64Remainder (MultU64x32 (Delta, 1000), TicksPerSecond, NULL);
283 CharCount = AsciiSPrint (Buffer,sizeof (Buffer),"%6a %6ld ms\n", Token, Milliseconds);
284 SerialPortWrite ((UINT8 *) Buffer, CharCount);
285 break;
286 }
287 }
288 }
289 } while (Key != 0);
290
291 CharCount = AsciiSPrint (Buffer,sizeof (Buffer),"Total Time = %ld ms\n\n", DivU64x64Remainder (MultU64x32 (TimeStamp, 1000), TicksPerSecond, NULL));
292 SerialPortWrite ((UINT8 *) Buffer, CharCount);
293 }
294
295 EFI_STATUS
296 GetEnvironmentVariable (
297 IN CONST CHAR16* VariableName,
298 IN VOID* DefaultValue,
299 IN OUT UINTN* Size,
300 OUT VOID** Value
301 )
302 {
303 EFI_STATUS Status;
304 UINTN VariableSize;
305
306 // Try to get the variable size.
307 *Value = NULL;
308 VariableSize = 0;
309 Status = gRT->GetVariable ((CHAR16 *) VariableName, &gEfiGlobalVariableGuid, NULL, &VariableSize, *Value);
310 if (Status == EFI_NOT_FOUND) {
311 if ((DefaultValue != NULL) && (Size != NULL) && (*Size != 0)) {
312 // If the environment variable does not exist yet then set it with the default value
313 Status = gRT->SetVariable (
314 (CHAR16*)VariableName,
315 &gEfiGlobalVariableGuid,
316 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
317 *Size,
318 DefaultValue
319 );
320 *Value = DefaultValue;
321 } else {
322 return EFI_NOT_FOUND;
323 }
324 } else if (Status == EFI_BUFFER_TOO_SMALL) {
325 // Get the environment variable value
326 *Value = AllocatePool (VariableSize);
327 if (*Value == NULL) {
328 return EFI_OUT_OF_RESOURCES;
329 }
330
331 Status = gRT->GetVariable ((CHAR16 *)VariableName, &gEfiGlobalVariableGuid, NULL, &VariableSize, *Value);
332 if (EFI_ERROR (Status)) {
333 FreePool(*Value);
334 return EFI_INVALID_PARAMETER;
335 }
336
337 if (Size) {
338 *Size = VariableSize;
339 }
340 } else {
341 *Value = DefaultValue;
342 return Status;
343 }
344
345 return EFI_SUCCESS;
346 }