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