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